为何全局模板变量初始化可行,类内初始化却报错?
类内模板静态成员与模板数据成员的报错原因及解决办法
第一个报错:invalid use of qualified-name ‘foo::null_string<T>::value’
- 原因:你在类
foo内部直接尝试定义嵌套模板null_string<T>的静态成员value,这不符合C++语法规则。类内部只能声明嵌套类/模板的静态成员,不能在类内部完成它们的定义(初始化)。嵌套在类中的模板结构体的静态成员,必须放到类外部去定义,并且要加上外层类的限定符foo::。
第二个报错:data member ‘null_str’ cannot be a member template
- 原因:C标准明确规定,类的非静态数据成员不能是模板;即使是静态数据成员,在C17之前也不能直接在类内定义模板静态变量,必须遵循「类内声明,类外定义」的规则;C++17之后可以用
inline关键字在类内直接定义静态模板变量,但语法要正确。
修正后的代码示例
C++17及以上版本写法
class foo { // 嵌套模板结构体的静态成员声明 template <class T> struct null_string { static const std::string value; }; // 用inline static直接在类内定义模板静态变量 template <class T> inline static const std::string null_str = null_string<const T&>::value; }; // 嵌套模板的静态成员必须在类外定义 template<class T> const std::string foo::null_string<T>::value = "";
C++17之前版本写法
class foo { // 嵌套模板结构体的静态成员声明 template <class T> struct null_string { static const std::string value; }; // 类内声明静态模板成员 template <class T> static const std::string null_str; }; // 定义嵌套模板的静态成员 template<class T> const std::string foo::null_string<T>::value = ""; // 类外定义静态模板成员null_str template<class T> const std::string foo::null_str = foo::null_string<const T&>::value;
为什么全局版本可以正常运行?
全局域中的模板结构体静态成员,可以直接在全局域完成定义,语法完全合法;而全局的模板变量(比如null_str)本身就是C++允许的语法,没有类成员的限制,所以可以正常编译运行。
内容的提问来源于stack exchange,提问作者Gianluca Bianco
相关产品推荐
相关产品推荐

