为什么我更喜欢类中的静态constexpr int而不是枚举类级别的积分常量?

问题描述 投票:10回答:3

C ++ 17更新:static constexpr变量隐式为inline,因此不需要外部定义。


原始问题:

假设我有一个常量列表,例如

struct Cls {
    static constexpr int N = 32;
    static constexpr int M = 64;
};

这当然表明我为这些添加定义以避免可能发生的ODR使用问题,因此我需要:

constexpr int Cls::N;
constexpr int Cls::M;

为什么我更喜欢这个

struct Cls {
    enum : int {
        N = 32,
        M = 64
    };
};

这节省了ODR使用的麻烦,因为NM更真实地只是常量而不是它们自己的对象(如果这只是标题,那就更大了)并且更短。如果需要,我可以明确指定类型enum : long long或其他任何东西。第一个有什么优势?

c++ c++11 enums constexpr
3个回答
5
投票

一个区别是你可以采取static constexpr但不是enum的地址。

另一个原因是旧版本的语言不支持constexpr(它是在C ++ 11中引入的)。

只有当值组合在一起时才使用enum。我还给enum一个描述这种关系的名字。我不会使用enum来定义不相关的常量。


2
投票

您的使用可能没有任何优势,因为您只是使用简单的固定整数值。

但是,[AFAIK] constexpr可以更通用,因为它允许从编译时可以评估的任何内容进行初始化。

来自type_traits

 /// integral_constant
  template<typename _Tp, _Tp __v>
    struct integral_constant
    {
      static constexpr _Tp                  value = __v;
      typedef _Tp                           value_type;
      typedef integral_constant<_Tp, __v>   type;
      constexpr operator value_type() const { return value; }
#if __cplusplus > 201103L
#define __cpp_lib_integral_constant_callable 201304
      constexpr value_type operator()() const { return value; }
#endif
    };

因此,constexpr可用于元编程。

以下是有点粗糙。

如果你有一个像这样的功能:

constexpr unsigned
bitmask(int bitno)
{

    return 1u << bitno;
}

您可能会发现以下用法:

constexpr unsigned BIT_0 = bitmask(0);
constexpr unsigned BIT_1 = bitmask(1);

2
投票

我很确定我会为此受到抨击,但......

我给你的原因是使用enum { }作为常量是对enum一词的误用。你没有列举任何东西。这是一种常见的误用,被授予;它有其实际优势;但这只是一种错误。应该有一种方法可以说“这只是一个编译时常量而不是其他”。 constexpr也不是那个,但它比枚举更接近。而且你无法枚举浮点值。

话虽这么说 - 当我想保护自己免受人们写void* ptr = &some_constant_value; std::cout << ptr;之类的东西时,我经常自己使用枚举作为常量

© www.soinside.com 2019 - 2024. All rights reserved.