c++ - 编译器认为 "A(A&)"暂时接受右值?

标签 c++ c++11 overload-resolution list-initialization

我有这个代码

struct A { A(); A(A&); }; 
struct B { B(const A&); }; 

void f(A); 
void f(B); 

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

令我惊讶的是,GCC 和 Clang 失败了。 Clang 举例说

Compilation finished with errors:
source.cpp:8:10: error: no matching constructor for initialization of 'A'
       f(A()); 
         ^~~
source.cpp:1:21: note: candidate constructor not viable: expects an l-value for 1st argument
    struct A { A(); A(A&); }; 
                    ^
source.cpp:1:16: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
    struct A { A(); A(A&); }; 
               ^
source.cpp:4:13: note: passing argument to parameter here
    void f(A); 

为什么他们选择第一个 f,而第二个 f 工作正常?如果我删除第一个 f,则调用成功。对我来说更奇怪的是,如果我使用大括号初始化,它也可以正常工作

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

他们都叫第二个f

最佳答案

这是一种语言怪癖。第一个f匹配更好,因为您的 A不需要转换来匹配参数类型( A ),但是当编译器尝试进行调用时,找不到合适的复制构造函数的事实会导致调用失败。在执行重载解决步骤时,该语言不允许考虑实际调用的可行性。

最匹配的标准引用 ISO/IEC 14882:2011 13.3.3.1.2 用户定义的转换序列 [over.ics.user]:

A conversion of an expression of class type to the same class type is given Exact Match rank, and a conversion of an expression of class type to a base class of that type is given Conversion rank, in spite of the fact that a copy/move constructor (i.e., a user-defined conversion function) is called for those cases.

对于列表初始化情况,您可能需要查看: 13.3.3.1.2 用户定义的转换序列[over.ics.user]

When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:

— Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.

— If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

因为重载解决方案必须在每种情况下为 f(A) 查看可行的构造函数和 f(B)它必须拒绝尝试绑定(bind) A() 的序列至A(A&)但是 B(const A&)还是可行的。

关于c++ - 编译器认为 "A(A&)"暂时接受右值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15852528/

相关文章:

c++ - 文件何时真正写入磁盘?是否保证在 std::ofstream 被破坏后立即将文件写入磁盘?

c++ - 如果我在 GetBuffer 之后不调用 ReleaseBuffer 怎么办?

c++ - 为什么 lambda 没有函数尝试 block ?

php - 使用C++加速PHP

c++ - 支持 c++11 的 Makefile

c++ - 使用 fstream 读取二进制文件并将结果存储在 vector 中

c++ - 防止隐式模板实例化

Swift 3 闭包重载解析

c++ - 为什么我的函数重载不如我的模板化函数重载?

c++ - 中级 C++ 开发人员的棘手面试问题