为什么即使我有未定义的成员函数,下面的代码也会编译?

Sam*_*rsa 8 c++ sfinae

我正在处理这段代码,并认为在点击构建按钮之前显然不会编译.我很惊讶它不仅编译,而且链接和工作.

如果我猜我会说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怪癖

bam*_*s53 3

该代码不合法​​。

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)