在C++中传递对数组的引用

use*_*274 35 c++

任何人都可以帮助我理解以下代码

#include <iostream>

void foo(const char * c)
{
   std::cout << "const char *" << std::endl;
}

template <size_t N>
void foo(const char (&t) [N])
{
   std::cout << "array ref" << std::endl;
   std::cout << sizeof(t) << std::endl;
}

int main()
{
    const char t[34] = {'1'};
    foo(t);

    char d[34] = {'1'};
    foo(d);
}
Run Code Online (Sandbox Code Playgroud)

输出是

const char *
array ref
34
Run Code Online (Sandbox Code Playgroud)

为什么第一个foo调用const char *版本?如何让它调用参考版本?

Lig*_*ica 15

转换为const char[N]to const char*被认为是"完全匹配"(主要是为了使文字更容易),并且在两个完全匹配之间,非模板函数优先.

您可以使用enable_ifis_array强制它执行您想要的操作.


强迫它的一种混乱方式可能是:

#include <iostream>

template <typename T>
void foo(const T* c)
{
   std::cout << "const T*" << std::endl;
}

template <typename T, size_t N>
void foo(const T (&t) [N])
{
   std::cout << "array ref" << std::endl;
}

int main()
{
    const char t[34] = {'1'};
    foo(t);

    char d[34] = {'1'};
    foo(d);
}

/*
array ref
array ref
*/
Run Code Online (Sandbox Code Playgroud)

我意识到OP char没有一些通用的T,但是这表明问题在于一个重载是模板而不是另一个.


asc*_*ler 5

让我们看看没有模板的这个修改过的例子.

void foo(const char * c)
{
    std::cout << "const char *" << std::endl;
}

void foo(const char (&t) [34])
{
    std::cout << "const char (&) [34]" << std::endl;
}

int main()
{
    const char t[34] = {'1'};
    foo(t);
}
Run Code Online (Sandbox Code Playgroud)

我的编译器说重载调用foo是模糊的.这是因为从数组到指针的转换被认为是"精确"转换序列,并不比重载解析的空转换序列更好(标准部分13.3.3.1.1.)

在原始代码中,模板参数N可以推导为34,但随后都是非模板foo(const char*),foo<34>(const char (&)[34])并且在重载决策中被认为是.由于转换规则两者都不比另一个好,因此非模板函数胜过模板函数.

解决问题似乎很棘手.看起来像is_array标题中的模板<type_traits>(如果可能的话,来自C++ 0x,或者如果没有则来自Boost)可能会有所帮助.