Enum 不是一个 constexpr?
Enum is not a constexpr?
我有这样一个源代码,有一个枚举,我希望它可以被评估为 constexpr,但编译器给我一个错误,它不是。为什么?
EventOrder 是 enum
还是 enum class
.
并不重要
#include <limits>
#include <type_traits>
enum class EventOrder
{
Last = 1'000'000,
Default = 0,
Logger = -1024,
First = -1'000'000
};
template <typename T>
constexpr inline std::underlying_type_t<T> num(T value) {
static_assert(std::is_enum<T>::value, "num can only be used on enumeration types");
return static_cast<std::underlying_type_t<T>>(value);
}
constexpr EventOrder sum(const EventOrder order, const std::underlying_type_t<EventOrder> orderDelta)
{
static_assert(order >= EventOrder::First, "Order Value out of bounds");
return static_cast<EventOrder>(num(order) + orderDelta);
}
int main( )
{
constexpr EventOrder e = EventOrder::Default;
sum(e, 2);
return 0;
}
它给出错误:
$ g++ -std=c++14 EventTest.cc
EventTest.cc: In function ‘constexpr EventOrder sum(EventOrder, std::underlying_type_t<EventOrder>)’:
EventTest.cc:23:2: error: non-constant condition for static assertion
static_assert(order >= EventOrder::First, "Order Value out of bounds");
^
EventTest.cc:23:2: error: ‘order’ is not a constant expression
为什么 order 不是 constexpr?
编辑 1
那么将参数作为模板变量传递是解决该问题的唯一方法吗?或者你知道一些不同的方法吗?
#include <limits>
#include <type_traits>
enum class EventOrder
{
Last = 1'000'000,
Default = 0,
Logger = -1024,
First = -1'000'000
};
template <typename T> constexpr inline std::underlying_type_t<T> num(T value)
{
static_assert(std::is_enum<T>::value, "num can only be used on enumeration types");
return static_cast<std::underlying_type_t<T>>(value);
}
template< typename T >
constexpr bool LimitedValue(const T value, const T min, const T max)
{
return value >= min && value <= max;
}
template <EventOrder orderl, std::underlying_type_t<EventOrder> orderr>
constexpr std::underlying_type_t<EventOrder> orderSum()
{
return num(orderl) + orderr;
}
template <EventOrder orderl, std::underlying_type_t<EventOrder> orderr>
constexpr EventOrder order()
{
static_assert(LimitedValue(orderSum<orderl, orderr>(), num(EventOrder::First), num(EventOrder::Last)), "order out of baunds");
return static_cast<EventOrder>(orderSum<orderl, orderr>());
}
int main()
{
EventOrder e = order<EventOrder::Default, 2>();
}
即使该函数是 constexpr
函数,它仍然可以使用非 const
参数调用。因此,当编译器处理该函数时,它无法知道 order
的值并且不能在 static_assert
.
中使用它
我有这样一个源代码,有一个枚举,我希望它可以被评估为 constexpr,但编译器给我一个错误,它不是。为什么?
EventOrder 是 enum
还是 enum class
.
#include <limits>
#include <type_traits>
enum class EventOrder
{
Last = 1'000'000,
Default = 0,
Logger = -1024,
First = -1'000'000
};
template <typename T>
constexpr inline std::underlying_type_t<T> num(T value) {
static_assert(std::is_enum<T>::value, "num can only be used on enumeration types");
return static_cast<std::underlying_type_t<T>>(value);
}
constexpr EventOrder sum(const EventOrder order, const std::underlying_type_t<EventOrder> orderDelta)
{
static_assert(order >= EventOrder::First, "Order Value out of bounds");
return static_cast<EventOrder>(num(order) + orderDelta);
}
int main( )
{
constexpr EventOrder e = EventOrder::Default;
sum(e, 2);
return 0;
}
它给出错误:
$ g++ -std=c++14 EventTest.cc
EventTest.cc: In function ‘constexpr EventOrder sum(EventOrder, std::underlying_type_t<EventOrder>)’:
EventTest.cc:23:2: error: non-constant condition for static assertion
static_assert(order >= EventOrder::First, "Order Value out of bounds");
^
EventTest.cc:23:2: error: ‘order’ is not a constant expression
为什么 order 不是 constexpr?
编辑 1
那么将参数作为模板变量传递是解决该问题的唯一方法吗?或者你知道一些不同的方法吗?
#include <limits>
#include <type_traits>
enum class EventOrder
{
Last = 1'000'000,
Default = 0,
Logger = -1024,
First = -1'000'000
};
template <typename T> constexpr inline std::underlying_type_t<T> num(T value)
{
static_assert(std::is_enum<T>::value, "num can only be used on enumeration types");
return static_cast<std::underlying_type_t<T>>(value);
}
template< typename T >
constexpr bool LimitedValue(const T value, const T min, const T max)
{
return value >= min && value <= max;
}
template <EventOrder orderl, std::underlying_type_t<EventOrder> orderr>
constexpr std::underlying_type_t<EventOrder> orderSum()
{
return num(orderl) + orderr;
}
template <EventOrder orderl, std::underlying_type_t<EventOrder> orderr>
constexpr EventOrder order()
{
static_assert(LimitedValue(orderSum<orderl, orderr>(), num(EventOrder::First), num(EventOrder::Last)), "order out of baunds");
return static_cast<EventOrder>(orderSum<orderl, orderr>());
}
int main()
{
EventOrder e = order<EventOrder::Default, 2>();
}
即使该函数是 constexpr
函数,它仍然可以使用非 const
参数调用。因此,当编译器处理该函数时,它无法知道 order
的值并且不能在 static_assert
.