带constexpr构造函数的模板与非模板类编译结果差异问题
C++17中模板类与非模板类含std::vector的constexpr构造函数差异
在C++17及更早标准里,std::vector并没有constexpr构造函数。这导致普通类如果包含std::vector作为成员,它的constexpr构造函数会直接编译失败,但模板类却能正常通过编译——只有当你声明constexpr的模板实例时,才会触发编译错误。
非模板类代码(编译失败)
#include <vector> class Y { public: constexpr Y(){} std::vector<int> v{}; }; int main() { Y ob; return 0; }
模板类代码(编译成功)
#include <vector> template<typename T> class X{ public: constexpr X(){} std::vector<T> v; }; int main() { X<int> ob; return 0; }
底层原理解析
这本质是模板的延迟实例化机制导致的:
- 对于非模板类,编译器在解析类定义阶段就会完整检查
constexpr构造函数的合法性。构造函数需要初始化成员v,而std::vector<int>的默认构造函数不是constexpr,因此直接触发错误。 - 对于模板类,编译器在模板定义阶段只会做基础语法检查,不会验证
std::vector<T>的构造函数是否符合constexpr要求——因为T是模板参数,此时还不确定具体类型,也不知道该构造函数是否会被用于常量表达式上下文。- 当创建普通的
X<int> ob实例时,编译器不需要验证构造函数的constexpr特性(constexpr修饰符仅表示构造函数可用于常量表达式,而非强制要求所有实例都必须是常量表达式),因此不会报错。 - 只有当声明
constexpr X<int> ob时,编译器才会实例化这个constexpr构造函数,此时才会发现std::vector<int>的构造函数不是constexpr,进而触发编译错误。
- 当创建普通的
GCC编译错误信息(非模板类代码)
error: call to non-‘constexpr’ function ‘std::vector<_Tp, _Alloc>::vector() [with _Tp = int; _Alloc = std::allocator<int>]’ constexpr Y(){}
内容的提问来源于stack exchange,提问作者Satyam Sharma
相关产品推荐
相关产品推荐

