2017-08-25 3 views
0

J'ai un tel code source, il y a une énumération qui j'espère pourrait être évaluée comme constexpr, mais le compilateur me donne une erreur, ce n'est pas le cas. Pourquoi? Peu importe si EventOrder est enum ou enum class.Enum n'est pas un constexpr?

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

Il donne l'erreur:

$ 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 

Pourquoi commander est pas un constexpr?

Modifier 1

Ainsi est le passage d'arguments comme variables de modèle seule façon de résoudre cela? Ou vous connaissez une manière différente?

#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>(); 

} 
+2

Les paramètres de fonction sont ** jamais ** constexpr. – ildjarn

+0

Que se passe-t-il si vous supprimez 'const' de' order' (juste 'OrderOrder order')? – 1201ProgramAlarm

+1

'std :: integral_constant' est une pseudo alternative. – Jarod42

Répondre

2

Même si la fonction est une fonction constexpr, il peut encore être appelé avec un argument non const. Par conséquent, lorsque le compilateur traite la fonction, il ne peut pas connaître la valeur de order et ne peut pas l'utiliser dans un static_assert.

+2

Cela n'aurait pas d'importance si la variable dans 'main' était constexpr. ;]] – ildjarn

+0

@jildjarn, merci d'avoir signalé l'erreur. –