2016-03-02 24 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); 
} 
相關問題