案例1
以下代码在MSVC和GCC中产生截然不同的结果:
#include <iostream>
template <typename T>
void foo(const T&) {
#ifdef _MSC_VER
std::cout << "foo(const T&): " << __FUNCDNAME__ << std::endl;
#else
std::cout << __PRETTY_FUNCTION__ << std::endl;
#endif
}
void foo(const char*) {
std::cout << "foo(const char*)" << std::endl;
}
int main() {
extern char s[];
foo(s);
}
char s[] = "abc";
MSVC 2013 Update 5,MSVC 2015 Update 1(也在http://webcompiler.cloudapp.net上尝试了更新2,结果相同):
foo(const char*)
GCC 5.3.0,Clang 3.7.0(DEMO):
void foo(const T&) [with T = char []]
案例2
现在让我们删除模板:
#include <iostream>
void foo(const char(&)[]) {
std::cout << "foo(const char(&)[])" << std::endl;
}
void foo(const char*) {
std::cout << "foo(const char*)" << std::endl;
}
int main() {
extern char s[];
foo(s);
}
char s[] = "abc";
MSVC产生错误:
error C2668: 'foo' : ambiguous call to overloaded function
could be 'void foo(const char *)'
or 'void foo(const char (&)[])'
GCC产生了另一个错误(同时包含-std=c++14
和-std=c++1z
):
main.cpp:3:29: error: parameter '<anonymous>' includes reference to array of unknown bound 'const char []'
void foo(const char(&)[]) {
Clang编译-std=c++14
和-std=c++1z
并输出:
foo(const char(&)[])
对于第一种情况,在我对C ++ 14的看法中,专业化void foo(const T&) [with T = char []]
不应该首先产生,所以MSVC是对的。但在C ++ 1z中,GCC和Clang是对的。
对于第二种情况,我认为使用C ++ 14 GCC是对的,使用C ++ 1z Clang是对的。
(这里C ++ 14和C ++ 1z之间的重要区别是CWG 393)
所以问题是,哪个编译器在C ++ 14(N4140)和C ++ 1z(N4567)中的第一个和第二个案例中是正确的?
另一个问题,我应该为哪个编译器(如果有的话)提交错误?
答案 0 :(得分:5)
const char(&)[]
是有效参数;我在一周前为GCC提交了相应的bug report 。
至于VC ++和Clang中哪一个是正确的,首先看this answer;如果s
被声明为const
,则MSVC 将正确无误。但是,因为它不是,我们必须在char const*
情况下执行数组到指针和限定转换 - 这使得另一个SCS成为这个的后续序列(资格调整,而不是左值变换,不会被忽略!),即Clang在两种情况下都是正确的。