例子:
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
行不调用构造函数 A
、B
或 C
。由于您的类没有声明复制构造函数(B
不是复制构造函数,因为它是模板)编译器创建默认移动构造函数(C
不是移动构造函数因为它是一个模板)并且它是第 2
行使用的默认移动构造函数。
在您的第二个示例中,B
和 C
的存在阻止了编译器生成默认构造函数,因此第 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/