Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 编译器认为;A(A)段“;暂时接受右值?_C++_C++11_Overload Resolution_List Initialization - Fatal编程技术网

C++ 编译器认为;A(A)段“;暂时接受右值?

C++ 编译器认为;A(A)段“;暂时接受右值?,c++,c++11,overload-resolution,list-initialization,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没有做到这一点。例如,克朗说 Compilation finished with errors: source.cpp:8:10: error: no matching constructor for initiali

我有这个密码

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

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

int main() { 
   f(A()); 
}
令我惊讶的是,GCC和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
,则调用成功。更奇怪的是,如果我使用大括号初始化,它也可以正常工作


他们都叫第二个
f

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

最接近匹配的标准引用ISO/IEC 14882:2011 13.3.3.1.2用户定义的转换序列[超过.ics.User]:

将类类型的表达式转换为相同的类类型时,会给出精确的匹配秩,并且 将类类型的表达式转换为该类型的基类时,尽管 对于这些情况,将调用复制/移动构造函数(即,用户定义的转换函数)

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

当列表初始化非聚合类类型T的对象时(8.5.4),重载解析选择构造函数 分两个阶段:

-最初,候选函数是T类和 参数列表由初始值设定项列表作为单个参数组成

-如果没有找到可行的初始值设定项列表构造函数,将再次执行重载解析,其中 候选函数是类T的所有构造函数,参数列表由元素组成 初始值设定项列表的


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

谢谢!对于
{…}
案例,我找不到这样的规则。这是否解释了
{…}
案例工作的原因?@johanneschaub-litb:我不确定,tbh,您正在使用带括号的init列表调用函数,因此规则肯定不同。@johanneschaub-litb请参阅[over.ics.list]。我认为这与[over.ics.ref]/3有关(我之前误读了您的代码):当形成可行函数的子集时,ctor
A(A&)
被认为是不可行的,因为它将临时引用绑定到非常量左值引用。
int main() { 
   f({A()}); 
}