为何满足条件却未隐式声明拷贝/移动构造函数?
为什么我的类C没有隐式生成拷贝/移动构造函数?
这个问题核心在于C++标准里特殊成员函数隐式生成的抑制规则,咱们一步步拆解清楚:
1. 移动构造函数的隐式生成限制
C++11及以后的标准规定:如果你的类显式声明了以下任意一个特殊成员函数,编译器会禁止隐式生成移动构造函数和移动赋值运算符:
- 自定义析构函数(
~C()) - 显式声明的拷贝构造函数(
C(const C&)) - 显式声明的拷贝赋值运算符(
C& operator=(const C&))
这是为了兼容旧代码:很多老代码会自定义析构函数,但没考虑移动语义,编译器如果自动生成移动构造,可能会导致意外的资源错误,所以干脆直接抑制。
2. 拷贝构造函数的隐式生成限制
反过来,如果你的类显式声明了移动构造函数或移动赋值运算符,编译器会禁止隐式生成拷贝构造函数和拷贝赋值运算符。
3. 结合你的场景分析
你的类C大概率是显式声明了上述会触发抑制的成员函数(比如自定义析构函数),导致编译器没有隐式生成移动构造。而std::is_invocable_r在内部检查时,刚好需要用到这个移动构造函数,所以才会在gcc7.3和clang5.0.1里编译失败。
当你取消注释移动构造函数(比如用= default显式默认它),这个构造函数就被明确生成了,std::is_invocable_r的检查通过,自然就能编译了。
举个实际的例子,你的类可能是这样的:
class C { public: // 显式声明析构函数,直接抑制移动构造的隐式生成 ~C() { /* 自定义析构逻辑 */ } // 取消注释后,显式默认移动构造,编译器生成它 // C(C&&) = default; // (1) };
4. 你觉得“满足隐式声明要求”的误区
你可能忽略了类中存在的其他显式声明的特殊成员函数(比如析构),这些函数是触发抑制规则的关键。哪怕你的类所有数据成员都支持移动,只要有这些显式声明,编译器就不会隐式生成移动构造。
内容的提问来源于stack exchange,提问作者yuri kilochek
相关产品推荐
相关产品推荐

