为什么这个operator = call不明确?

And*_*ost 10 c++ explicit implicit-conversion c++11

我正在使用转发构造函数创建一个瘦派生类.(请耐心等待,我必须使用缺少继承构造函数的GCC 4.7.2).

在第一次尝试时,我忘了添加explicit关键字并出错.有人可以解释为什么会发生这种特殊错误吗?我无法搞清楚事件的顺序.

#include <memory>

template<typename T>
struct shared_ptr : std::shared_ptr<T>
{
  template<typename...Args>
  /*explicit*/ shared_ptr(Args &&... args)
    : std::shared_ptr<T>(std::forward<Args>(args)...)
  {}
};

struct A {};

struct ConvertsToPtr
{
  shared_ptr<A> ptr = shared_ptr<A>(new A());
  operator shared_ptr<A> const &() const { return ptr; }
};

int main()
{
  shared_ptr<A> ptr;
  ptr = ConvertsToPtr(); // error here
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误:

test.cpp: In function ‘int main()’:
test.cpp:28:23: error: ambiguous overload for ‘operator=’ in ‘ptr = ConvertsToPtr()’
test.cpp:28:23: note: candidates are:
test.cpp:9:8: note: shared_ptr<A>& shared_ptr<A>::operator=(const shared_ptr<A>&)
test.cpp:9:8: note: shared_ptr<A>& shared_ptr<A>::operator=(shared_ptr<A>&&)
Run Code Online (Sandbox Code Playgroud)

Avi*_*viv 7

这也符合情况g++4.8.4有以下:
g++ -g -pedantic --std=c++11 -o test main.cpp
将VS2015的设置都是默认.

问题是编译器尝试将返回的临时转换ConvertsToPtr()shared_ptr对象.当编译器与explicit关键字一起使用时,使用构造函数永远不会发生此转换.但是,在使用gdb它进行检查时,它似乎正在使用shared_ptr<A> const &()转换函数来匹配相应的类型.然后,这个转换返回一个const shared_ptr &在调用赋值运算符时没有歧义(这也与wojciech Frohmberg的结果相匹配).

但是,如果explicit省略,则shared_ptr返回一个对象.这可以与赋值运算符的rvalue版本或const lvalue版本匹配.

根据N4296,表-11,然后我们在构造之后有conversion constructor一个rvalue of shared_ptr物体.但是,重载决策会找到两个匹配,这两个匹配都在Exact Match(rvalue版本Identity matching而另一个版本不足Qualification matching)下排名.

我也做了检查,VS2015并在评论中说明,它的工作原理.但是使用一些cout调试可以看到const lvalue赋值 rvalue优先于 右值 const lvalue refrence版本对应物.

编辑:我在标准中看得更深一点并添加修改.关于结果的删除文本VS2015是错误的,因为我没有定义两个任务.当两个赋值都被声明时,它确实更喜欢rvalue.

我假设VS编译器与排名中IdentityQualification匹配区别开来.但是,正如我总结的那样,VS编译器是错误的.该g++编译器服从给定的标准.但是,由于GCC 5.0可以作为Visual studio工作,编译器错误的可能性很小,所以我很乐意看到另一个专家见解.

编辑:在13.3.3.2中,其中一个抽奖破坏者,在我写的关于它的更好的排名后,是:

- S1和S2是引用绑定(8.5.3),并且都不引用没有ref-qualifier声明的非静态成员函数的隐式对象参数,S1将rvalue引用绑定到rvalue,S2绑定左值引用.

附加的示例显示给定的rvalue(不是右值引用)应该匹配const int &&over const int &.因此我想,即使我们有&&类型而不是const &&类型,也可以安全地假设它与我们的案例相关.毕竟我认为GCC4.7,4.8毕竟是错误的.