【问题标题】:How template influence implicitly-declared-rules in C++?模板如何影响 C++ 中的隐式声明规则?
【发布时间】:2018-10-01 12:39:55
【问题描述】:

例子:

template<class T> class A{
  public:
    A(){}
    template<class U> A(A<U> &){}
  private:
    template<class U> A(A<U>&&){}
};

int main() {
  A<int> a1;// legal
  A<int> a2(std::move(a1));//legal. it calls implicitly-declared constructor.
}

但是当我删除 A(){} 时:

template<class T> class A{
  public:

    template<class U> A(A<U> &){}
  private:
    template<class U> A(A<U>&&){}
};

int main() {
  A<int> a1;// illegal. 3
  A<int> a2(std::move(a1));
}

  • 如果模板构造函数不影响隐式声明的规则。为什么它变得非法?
  • 如果模板构造函数确实影响隐式声明的规则,为什么A&lt;int&gt; a2(std::move(a1)); 在第一个示例中不是非法的?

在 gcc 和 ubuntu 上测试过。

【问题讨论】:

  • 谁告诉你模板构造函数不会影响隐式声明规则
  • 但是为什么“A a2(std::move(a1));”合法的? @NathanOliver
  • @Long on MSVC A&lt;int&gt; a2(std::move(a1)); 也是非法的。
  • @Rhathin 你用的是什么版本?它适用于我的答案细节,它应该。
  • @Rhathin 你真的应该更新。版本 11 (MSVS 2012) 的 C++11 合规性很差。 MSVS 2017 具有更好的支持和合规性。 (我认为现在甚至可能是完全合规和支持)

标签: c++ c++11 templates constructor


【解决方案1】:

template<class T> class A{
  public:
    A(){} // A
    template<class U> A(A<U> &){} // B
  private:
    template<class U> A(A<U>&&){} // C
};

int main() {
  A<int> a1; // 1
  A<int> a2(std::move(a1)); // 2
}

1 行调用构造函数A2 行不调用构造函数 ABC。由于您的类没有声明复制构造函数(B 不是复制构造函数,因为它是一个模板),因此编译器会创建一个默认的移动构造函数(C 不是移动构造函数,因为它是一个模板),它就是2 行使用的默认移动构造函数。

在您的第二个示例中,BC 的存在会阻止编译器生成默认构造函数,因此行 1 不再编译,但如果这样做,行 2 仍将编译,因为它会使用编译器生成的移动构造函数。


所以,这里的规则是复制或移动构造函数永远不是模板构造函数,但构造函数模板仍然算作构造函数,因此它们禁用默认构造函数。这意味着在检查您的类是否会生成默认的复制或移动构造函数时,您需要忽略它们。有关何时获取的规则,请参见:Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?

【讨论】:

  • ... 但是构造函数模板仍然算作构造函数,因此它们禁用了默认构造函数。
  • @Quentin 好建议。编辑于。
猜你喜欢
  • 1970-01-01
  • 2019-10-05
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多