C++11 统一初始化:字段初始化值不是常量

4
我将尝试实例化一组字符串,如下所示:

class POI {
public:
...
  static const std::set<std::string> TYPES { "restaurant", "education", "financial", "health", "culture", "other" };
...
}

现在,当我这样做时,我会得到这些错误(都在这一行上):
error: field initializer is not constant
 static const std::set<std::string> TYPES { "restaurant", "education", "financial", "health", "culture", "other" };
error: in-class initialization of static data member 'const std::set<std::basic_string<char> > POI::TYPES' of non-literal type
error: non-constant in-class initialization invalid for static member 'POI::TYPES'                                                              
error: (an out of class initialization is required)
error: 'POI::TYPES' cannot be initialized by a non-constant expression when being declared

如果我认为集合内的字符串不是被视为常量,那么这就有意义了。这真的是问题所在吗?不幸的是,我找不到一种声明初始化器内的字符串为const的方法..这可能吗?


5
NSDMI不适用于静态成员。 - Piotr Skotnicki
1
这就是 N 的含义 :-) (非静态数据成员初始化器)。 - Jarod42
2个回答

8

你必须在外部初始化静态变量,代码如下:

#include <set>
#include <string>

class POI {
public:
  static const std::set<std::string> TYPES;
};
const std::set<std::string> POI::TYPES { "restaurant", "education", "financial", "health", "culture", "other" };

根据标准规定(第9.4.2节),这将适用于整数/枚举类型:

如果静态数据成员是const整数或const枚举类型,则其在类定义中的声明可以指定常量初始化器,该常量初始化器应为整数常量表达式。在这种情况下,该成员可以在其作用域内的整数常量表达式中出现。


7
在C++中,初始化器旨在成为定义的一部分,而不是声明的一部分。对于const整数和enum类型,这种限制得到了放宽。在C++11中,进一步添加了对字面类型constexpr成员的指令。 /p3
如果非易变静态数据成员属于整数或枚举类型,则其在类定义中的声明可以指定花括号或等于初始化程序,在其中每个初始化程序子句都是常量表达式(5.20)的赋值表达式。字面类型的静态数据成员可以在类定义中使用constexpr说明符声明;如果这样做,则其声明应指定一个花括号或等于初始化程序,在其中每个初始化程序子句都是常量表达式。[ ... ]如果该成员在程序中被odr-used(3.2),则仍必须在命名空间范围内定义该成员,并且命名空间范围定义不得包含初始化程序。
由于这不适用于您的情况,因此您应该像此示例所示那样在线外初始化您的静态变量。
class POI {
public:
  static const std::set<std::string> TYPES;
};

const std::set<std::string> POI::TYPES = {
   "restaurant", "education", "financial", "health", "culture", "other" 
};

  1. 对于字面类型,应该使用constexpr而不是const
  2. 使用constexpr时,类内初始化器实际上是必需的。
- T.C.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接