剪:
#include <optional>
template <typename>
class MyOpt;
template <typename T>
MyOpt(T) -> MyOpt<T>;
template <typename T>
class MyOpt : private std::optional<T>
{
public:
using std::optional<T>::optional;
using std::optional<T>::operator=;
};
int main() {
MyOpt o{42};
o=52;
return 0;
}
此代码无法编译,并出现一些歧义错误:
错误:“operator=”的重载不明确(操作数类型为“MyOpt”和“int”)
注意:候选人:'constexpr MyOpt& MyOpt::operator=(const MyOpt&)'
注意:候选人:'constexpr MyOpt& MyOpt::operator=(MyOpt&&)'
参见https://godbolt.org/z/jvMMGh9Gn
此失败的原因是什么?是否可以“修复”(c++20 可供处置),以便在派生类中我不必重新实现赋值运算符?
问题在于您正在尝试调用无法为标量类型调用的继承赋值运算符。这是 cppreference 中的重载 (4)。请注意以下关于此“转发”构造函数的引用:
该函数不参与重载决策,除非... 并且以下至少一项为真:
不是标量类型;T
不是std::decay_t<U>
。T
在您的情况下,
T
是int
,这是一种标量类型,std::decay_t<U>
也是int
,因此它也是T
。
这个原因的一个简单演示是使用非标量类型;然后,一切正常:https://godbolt.org/z/cbasffaEM.