2017-01-03 27 views
7
#include <iostream> 
using namespace std; 

void f(const char* arg) 
{ 
    cout << "arg is a pointer" << endl; 
} 

template<size_t N> 
void f(const char (&arg)[N]) 
{ 
    cout << "arg is an array." << endl; 
} 

int main() 
{ 
    f(""); 
} 

我的编译器是叮当3.8。为什么clang将字符串字面量当作指针而不是数组?

的输出是:

arg是指向

然而,根据cppreference.com

类型的前缀的字符串文字的是为const char [] 。

为什么重载分辨率不像预期的那样表现?

+2

等效的例子,但抽象了模板:http://melpon.org/wandbox/permlink/0nGenu5Ysj40wS8u –

+0

[密切相关](https://stackoverflow.com/questions/16708307/is-it-possible-to -legally-overload-a-string-literal-and-const-char),可能是重复。你怎么看? –

回答

8

它不会像预期的那样,你只需要调整您的期望;-)

const char[1]const char (&)[1]是不同的类型。

转换为const char*(数组到指针转换)和const (&char)[1](标识转换)都被认为是完全匹配,但非模板比模板匹配得更好。

如果你写一个非模板尺寸专用的过载,

void f(const char (&arg)[1]) 

,该函数调用是不明确的,你会得到一个错误。

+2

太慢了。 :(仅供参考,N4141的表12中列出了相关的标准 –

1

@ molbdnilo的回答是正确的。添加一个细节:你的直觉是正确的,编译器宁愿通过调用模板来避免数组到指针的转换。根据[over.ics.rank]§13.3.3.2/ 3.2.1,左值转换(左值到右值,数组到指针和函数到指针)在过载排名中被明确忽略。

有一个workaround:添加一个假的volatile恢复过载偏好的平衡。在使用参数之前,请确保将其删除const_cast

相关问题