字符串文字左值和右值引用的函数重载

Bap*_*tou 16 c++ language-lawyer overload-resolution value-categories

test对于左值空字符串,左值非空字符串和右值字符串,下面的函数已重载。我尝试使用Clang和GCC进行编译,但在两种情况下都没有达到我期望的结果。

#include <iostream>

void test(const char (&)[1]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

template <unsigned long int N>
void test(const char (&)[N]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

void test(char*&&){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

int main(){
    char str1[] = "";
    char str2[] = "test";
    test("");
    test("test");
    test(str1);
    test(str2);
}
Run Code Online (Sandbox Code Playgroud)

使用clang 版本6.0.0-1ubuntu2的输出:

#include <iostream>

void test(const char (&)[1]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

template <unsigned long int N>
void test(const char (&)[N]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

void test(char*&&){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

int main(){
    char str1[] = "";
    char str2[] = "test";
    test("");
    test("test");
    test(str1);
    test(str2);
}
Run Code Online (Sandbox Code Playgroud)

使用g ++ (MinGW.org GCC-8.2.0-3)输出

clang++ test.cpp -o test.out && ./test.out
void test(const char (&)[1])
void test(const char (&)[N]) [N = 5]
void test(char *&&)
void test(char *&&)
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 哪个编译器正确?
  2. 铿锵,为什么test(str1)test(str2)选择右值过载,而他们的左值?
  3. 使用GCC,为什么通话test(str1)不明确?
  4. 有这种情况的标准规则吗?
  5. 如何解决最后两个电话?

谢谢。

son*_*yao 13

  1. 哪个编译器正确?

GCC是正确的。

  1. 使用clang,为什么str1和str2是左值时选择右值重载?

Clang错误test(str1);,应该模棱两可。对于test(str2);str2可以隐式转换为指针,即数组到指针的衰减。转换后的char*是右值。由于与#3相同的原因,隐式转换序列具有相同的排名,因此首选非模板功能;test(char*&&)被选中。

  1. 使用gcc,为什么用str1调用是不明确的?

对于test(const char (&)[1])被调用,从资格转换char[1]const char[1]是必需的; 对于test(char*&&)被称为,需要阵列到指针转换。两者均符合完全匹配的资格,并且具有相同的排名。

  1. 有这种情况的标准规则吗?

请参见重载解析中隐式转换序列的排名以及隐式转换

  1. 如何解决最后两个电话?

这取决于您的意图。