2016-03-02 123 views
1

std::underlying_type与非枚举类型一起使用时会调用未定义的行为。 但未定义的行为出现在哪里?std :: underlying_type:SFINAE是否阻止未定义的行为?

在此代码:

template<typename E> 
constexpr std::enable_if_t<std::is_enum<E>::value, std::underlying_type_t<E>> IntEnum(E e) 
{ 
    return static_cast<std::underlying_type_t<E>>(e); 
} 

我试图用std::enable_if以防止用户调用IntEnum与非枚举类型。但由于enable_if在决定是否可以调用该函数之前进行了评估,因此也会对其模板参数进行评估,包括std::underlying_type_t<E>。如果用非枚举类型调用此UB,那么也是如此?我该如何改变它?

+0

BTW,这不是UB,但编译错误。 – Jarod42

+0

http://en.cppreference.com/w/cpp/types/underlying_type似乎说不然,是一个错误? –

+0

@AlexandreS。我相信那是一个错误。如果'std :: underlying_type'的'Condition'规范被写为* Requires *子句,那只会是未定义的行为,事实并非如此。有未定义的行为来实例化模板似乎很奇怪。 – TartanLlama

回答

2

typename std::underlying_type<E>::type即使对于非枚举类型也是如此(并且不是SFINAE友好的)。

您可以使用一个间接延缓评价,并SFINAE友好:

template<typename E> 
constexpr 
typename std::enable_if_t<std::is_enum<E>::value, std::underlying_type<E>>::type 
IntEnum(E e) 
{ 
    return static_cast<std::underlying_type_t<E>>(e); 
} 

Demo

0

您可以防止编译与static_assert

template<typename E> 
constexpr auto IntEnum(E e) 
{ 
    static_assert(std::is_enum<E>::value, "E must be an enum"); 
    return static_cast<std::underlying_type_t<E>>(e); 
}