c++ - 模板如何影响 C++ 中的隐式声明规则?

标签 c++ c++11 templates constructor

例子:

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<int> a2(std::move(a1));第一个例子是非法的?

在 ubuntu 上用 gcc 和 clang 测试。

最佳答案

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 调用构造函数 A。但是 2 行不调用构造函数 ABC。由于您的类没有声明复制构造函数(B 不是复制构造函数,因为它是模板)编译器创建默认移动构造函数(C 不是移动构造函数因为它是一个模板)并且它是第 2 行使用的默认移动构造函数。

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


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

关于c++ - 模板如何影响 C++ 中的隐式声明规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52591376/

相关文章:

c++ - 将数组从函数返回到 main

c++ - 读写文件

c++ - 如何使用 std::greater 对 C++ 映射键进行排序?

c++ - 提供基类(或不可复制)和虚拟继承的类型

c++ - 如何使用 std::vector 防止内存重新分配

c++ - 嵌套类模板特化问题

c++ - 将一个dll文件导入另一个IDL文件

c++ - 类型别名错误

C++:如何检查模板函数中使用的数据类型?

c++11 - 如果我有 T&& temp = std::move(other);然后在按值接受 T 的函数上使用它