C++ 引用未知边界数组的不同编译器的奇怪行为

C++ 引用未知边界数组的不同编译器的奇怪行为,c++,visual-c++,g++,clang++,c++17,C++,Visual C++,G++,Clang++,C++17,案例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

案例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";
GCC 5.3.0,Clang 3.7.0():

案例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";
GCC产生另一个错误(同时出现
-std=c++14
-std=c++1z
):


对于第一种情况,在我对C++14的看法中,专门化
void foo(const T&)[with T=char[]]
首先不应该产生,因此MSVC是正确的。但在C++1z中,GCC和Clang是正确的

对于第二种情况,我认为使用C++14 GCC是正确的,使用C++1z Clang是正确的

(这里C++14和C++1z之间的重要区别是)


所以问题是,在C++14(N4140)和C++1z(N4567)中,哪种编译器在第一种和第二种情况下是正确的

另一个问题是,我应该为哪个编译器(如果有的话)提交错误?

const char(&)[]
是CWG 393的有效参数;就在一周前,我为GCC提交了相应的文件


至于VC++和Clang中哪一个是正确的,首先看;如果
s
被声明为
const
,则MSVC是正确的。然而,由于不是这样,我们必须在
char const*
情况下执行指向指针的数组和限定转换,这使得其他SCS成为这个SCS的子序列(限定调整,而不是左值转换,不被忽略!),即在这两种情况下,Clang都是正确的。

const char(&)[]
??如果您将
s
设置为
const char[]
,则在这三种情况下都会收到类似的错误消息compilers@melak47这就是问题所在,到
const
的限定转换在这里很重要。但在这两种情况下都会执行限定转换,而且转换是不同的(
char*
->
char const*
char(&)[]
->
char const(&)[]
),那么一个序列怎么可能是另一个序列的子序列呢?限定转换只对指针进行。数组引用直接绑定,这就是最重要的。
void foo(const T&) [with T = char []]
#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";
error C2668: 'foo' : ambiguous call to overloaded function
could be 'void foo(const char *)'
or       'void foo(const char (&)[])'
main.cpp:3:29: error: parameter '<anonymous>' includes reference to array of unknown bound 'const char []'
     void foo(const char(&)[]) {
foo(const char(&)[])