对非常量成员使用 constexpr 是否有效
Is the use of constexpr valid with non-const members
Background
我想要实现的目标:我正在尝试实现类似Java枚举的东西(即具有一些附加功能的枚举(。我想出了一个使用两个类的解决方案,其中一个类表示一个值,另一个类使用静态变量作为可能值的枚举来表示每个值。我希望它真正替代枚举,包括在模板实例化中使用枚举值的可能性。为此,枚举值需要是一个常量表达式(constexpr(。但是,我不确定我是否正确使用了 constexpr。
《守则》
这是我想出的代码:
class EnumType {
public:
enum Enum {val_A, val_B, val_C};
friend class EnumTypeList;
EnumType()
: m_ID(val_A), m_foo(0) {}
constexpr operator Enum() const {return m_ID;};
constexpr unsigned int getFoo() const {return m_foo;};
protected:
constexpr EnumType(const Enum v, const int foo)
: m_ID(v), m_foo(foo) {}
private:
Enum m_ID;
int m_foo;
};
class EnumTypeList {
public:
static constexpr EnumType A = EnumType(EnumType::val_A, 5);
static constexpr EnumType B = EnumType(EnumType::val_B, 4);
static constexpr EnumType C = EnumType(EnumType::val_C, 8);
};
类EnumType
保存每个值的信息并提供一些附加函数(这里它存储可以使用getFoo()
函数访问的附加值m_foo(。枚举本身由包含静态 constexpr 变量的EnumTypeList
表示,其中每个变量表示枚举的可能值。这段代码允许我使用 EnumTypeList
中的变量代替EnumType::Enum.
即使在模板中,如以下代码所示:
template <EnumType::Enum T>
class Test {
public:
void test() {
std::cout << "Enum is not A" << std::endl;
}
};
template <>
class Test<EnumType::val_A> {
public:
void test() {
std::cout << "Enum is A" << std::endl;
}
};
int main() {
Test<EnumTypeList::A> a;
a.test();
Test<EnumTypeList::B> b;
b.test();
// this shouldn't compile
/*EnumType x = EnumTypeList::C;
Test<x> c;
c.test();*/
}
这如我所期望的那样工作——如上所述,我可以在模板实例化中使用 EnumTypeList
中的值代替EnumType::Enum
,但我不能用EnumType x = EnumTypeList::C;
问题所在
虽然代码在 gcc 和 clang 下没有任何警告的情况下正确编译,但我不确定我是否正确使用了 constexpr。问题是,虽然EnumType
构造函数和转换运算符operator Enum()
是constexpr,但它们都访问变量m_ID
和m_foo
不是常量(因为我需要赋值运算符(。
这很好,文本类型的成员是可修改的。
为了在常量表达式中使用类型,您必须使用常量参数构造它,但这没关系,因为您可以这样做;
static constexpr EnumType A = EnumType(EnumType::val_A, 5);
构造的对象是一个有效的常量表达式,因此可用于初始化constexpr
变量A
。 您不修改对象的成员,因此它们是否可修改并不重要。
特别是Clang对常量表达式非常严格,如果你做错了什么,它会给出错误。
此对象可用于需要常量表达式的情况:
constexpr EnumType A5(EnumType::val_A, 5);
例如
constexpr int i = A5.getFoo();
此对象不能:
EnumType A6(EnumType::val_A, 6);
constexpr int i = A6.getFoo(); // error
- 是否可以使用if constexpr删除控制流语句
- 更多constexpr容器是否需要mark_immutable_if_consexpr
- 添加静态constexpr成员是否会更改结构/类的内存映射
- 是否可以将带有字符串化运算符的宏转换为 constexpr?
- 将INT32BE宏转换为 constexpr 是否正确?
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 任意大小的 constexpr 数组是否可以用作 switch 语句中的案例?
- 在 constexpr 构造函数中初始化数组是否合法?
- G++ 编译器是否在未使用返回值的情况下将 constexpr 函数视为常规函数?
- 是否使用静态 constexpr 变量 odr?
- 是否可以跨多个源文件构建 constexpr 数据结构?
- 如何判断是否在编译时计算了"constexpr"(无需手动检查)
- 是否可以将变体的索引作为 constexpr 变量获取?
- 将静态 const 成员重新声明为 constexpr 是否会自动使其符合内联条件
- 使用constexpr是否具有递减的回报
- constexpr是否暗示noexcept
- 对非常量成员使用 constexpr 是否有效
- 类型不完整的嵌套静态constexpr.是否有效的c++
- 如果标准保证使用初始值设定项,constexpr 是否? 'constexpr(constexpr auto x = f(); x) { }'
- constexpr是否暗示内联?