C++无法将字符串文字“const char []”传递给参数类型为“const T&”的函数,其中T是char[]的typedef

ca1c2owp  于 2023-03-05  发布在  其他
关注(0)|答案(1)|浏览(180)

在以下代码中,main()中的局部变量rccfoo()中的参数r具有相同的类型const CC&。成功地为局部变量赋值了字符串文本,而将字符串文本传递给foo()则编译失败。为什么相同类型会有不同的行为?
注意:在Visual Studio 2019中编译

typedef char CC[5];

void foo(const CC& r)
{
    std::cout << r << std::endl;
}

void bar(const char(&r)[])
{
    std::cout << r << std::endl;
}

int main()
{
    const CC &rcc = "ex"; // Pass compilation with all standards
    const char(&rchar)[] = "ex"; // Pass compilation with all standards
    std::cout << rcc << ' ' << rchar << std::endl;
    bar("ex"); // Pass compilation with ISO C++20 standard only
    foo("ex"); // Fails compilation with all standards
    return 0;
}

我尝试将字符串文本传递给参数类型为const T&的函数,其中Tchar[]的typedef。
我期望对函数参数赋值的行为与对相同类型的局部变量赋值的行为相同。
我收到以下编译错误:

error C2664: 'void foo(const CC (&))': cannot convert argument 1 from 'const char [3]' to 'const CC (&)'  
message : Reason: cannot convert from 'const char [3]' to 'const CC'  
message : There is no context in which this conversion is possible  
message : see declaration of 'foo'
bjp0bcyl

bjp0bcyl1#

bar("ex");自C20以来就是良构的,因为C20允许隐式地删除指针/引用到数组的数组边界(参见https://github.com/cplusplus/papers/issues/565及其参考文献)。
因此bar的参数自C++20起将直接绑定到字符串字面量。
我认为const CC &rcc = "ex";应该可以工作,因为应用的初始化规则链中的第一项是[dcl.init.ref]/5.4.2,根据该规则,引用被绑定到从目标类型的纯右值实现的临时值,而没有引用限定符,该限定符被隐式地从初始化表达式转换为。
“* 隐式转换 *”在[conv.general]/3中定义为等效于来自原始初始化表达式的虚变量t的声明,在本例中为

const char t[5] = "ex";

这种初始化是格式良好的,因为从字符串常量初始化字符数组的规则允许在零初始化的数组中保留额外的空间,请参见[dcl.init.string]/3。
因此,rcc将绑定到一个临时的(且生存期延长的)const char[5]数组,该数组初始化为字节序列ex\0\0\0
我认为foo("ex");也应该没有区别。
但是我不能完全确定这是预期的解释。GCC和Clang都不接受const CC &rcc = "ex";,我认为[conv.general]/3有一些问题。

相关问题