我正在处理这段代码,并认为在点击构建按钮之前显然不会编译.我很惊讶它不仅编译,而且链接和工作.
如果我猜我会说SFINAE负责编译......是吗?
struct BaseClass
{
public:
BaseClass() {}
template<typename T>
BaseClass(const T& a_other)
{
int i = 0; // for break point
}
template<typename T>
BaseClass& operator= (const T& a_other)
{
int i = 0; // for break point
return *this;
}
private:
BaseClass(const BaseClass& a_other); // Does not have a definition
BaseClass& operator= (const BaseClass& a_other); // Does not have a definition
};
struct MyClass : public BaseClass
{
};
int main()
{
MyClass i, j;
i = j;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:我使用的是Visual-C++ 2008,也许这是一个奇怪的VS怪癖
该代码不合法。
i = j调用 中隐式定义的复制赋值运算符MyClass。该函数为其每个子对象调用复制赋值运算符,包括直接基类 [class.copy 12.8 p28]。
如果您将代码添加到 BaseClass 的复制赋值运算符中,您可以看到 VS 出了问题:
template<typename T>
BaseClass& operator= (const T& a_other)
{
std::cout << typeid(T).name() << '\n';
int i = 0; // for break point
return *this;
}
Run Code Online (Sandbox Code Playgroud)
对我来说,这会打印出“struct MyClass”。VSBaseClass通过直接传递接收到的参数来调用复制赋值运算符MyClass:operator=,而不仅仅是BaseClassj的子对象。
SFINAE 没有发挥作用,因为模板函数没有失败。VS 只是错误地生成了隐式复制赋值运算符。
总结一下:VS 生成隐式复制赋值运算符为
MyClass &operator=(const MyClass& rhs) {
static_cast<BaseClass&>(*this).operator=(rhs);
return *this;
}
Run Code Online (Sandbox Code Playgroud)
什么时候应该是:
MyClass &operator=(const MyClass& rhs) {
static_cast<BaseClass&>(*this).operator=(static_cast<const BaseClass&>(rhs));
return *this;
}
Run Code Online (Sandbox Code Playgroud)