Why should I prefer static constexpr int in a class over enum for class-level integral constants?

回眸只為那壹抹淺笑 提交于 2019-12-04 18:10:47

问题


C++17 Update: static constexpr variables are implicitly inline so there's no external definition necessary.


Original question:

Let's say I have a list of constants such as

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

This of course suggests that I add definitions for these to avoid ODR-usage issues that may occur so I need:

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

Why should I prefer this over

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

Which saves me of the ODR-usage headaches since N and M are more truly just constants and not objects in their own right (a bigger deal if this is header-only) and is shorter. I could explicitly specify the type enum : long long or whatever if need be. What is the advantage of the first?


回答1:


One difference is that you can take the address of a static constexpr but not of an enum.

Another is that constexpr isn't supported by older versions of the language (it was introduced in C++11).

I'd use enum only if the values belong together. I'd also give the enum a name that describes that relationship. I wouldn't use an enum for defining unrelated constants.




回答2:


Perhaps no advantage for your usage because you're just using simple fixed integer values.

But, [AFAIK] constexpr can be more general as it allows initialization from anything that can be evaluated at compile time.

From 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
    };

Thus, constexpr has usage in metaprogramming.

The following is a bit rough.

If you had a function like:

constexpr unsigned
bitmask(int bitno)
{

    return 1u << bitno;
}

You might find a usage such as:

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



回答3:


I'm pretty sure I'm going to get flamed for this, but...

The reason I would give you is that using enum { } for constants is a misuse of the term enum. You're not enumerating anything. It's a common misuse, granted; it has its practical advantages; but it's just kind of wrong. There should be a way to say "this is just a compile-time constant and nothing else". constexpr isn't that thing either, but it's closer than enum. And it's rightly the case that you can't enum floating-point values.

That being said - I often use enums for constants myself, when I want to protect myself against people writing something like void* ptr = &some_constant_value; std::cout << ptr;



来源:https://stackoverflow.com/questions/35213098/why-should-i-prefer-static-constexpr-int-in-a-class-over-enum-for-class-level-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!