Creating coordinated enumerations comparable to the base type

I am trying to make adjusted enumerations in my program compatible with the base type, but the following code does not work. Is this because of poor support for C ++ 11 in the compiler I use (VC11), or is it because the code violates some rules from the C ++ 11 standard? In the latter case, what rules are definitely violated (links to specific standard offers are welcome)?

#include <type_traits> enum class Test: short int { A,B,C }; template<typename E> bool operator != (E e, typename std::underlying_type<E>::type n) { return static_cast<typename std::underlying_type<E>::type>(e) != n; } template<typename E> bool operator != (typename std::underlying_type<E>::type n, E e) { return static_cast<typename std::underlying_type<E>::type>(e) != n; } int main() { short int x = 123; x != Test::B; // compilation error } 

This is why I think that my code should be compatible with C ++ 11. Quote from the C ++ 11 standard (14.8.3.1):

For each function template, if the argument output and verification succeed, the template arguments (output and / or explicit) are used to synthesize the declaration of one function template specialization, which is added to the candidate functions that will be used when resolving overloads. If,> for a given function template, the argument is not output, then no function is added to the set of> candidate functions for this template.

EDIT. My code is not compatible with C ++ 11 (thanks for explaining Vaughn Caton and Andy Proul). Alternative working code is provided in Andy Prole's answer.

PS In the end, I ended up creating unoccupied enumerations using namespaces:

 namespace Test_ { enum Test { A,B,C }; }; using Test_::Test; namespace Test2_ { enum Test2 { Z,Y,B }; }; using Test2_::Test2; 
+4
source share
2 answers

Section 14.8.2, Clause 8 of the C ++ 11 Standard State:

If the substitution results in an invalid type or expression, the deduction type is not performed. An invalid type or expression is one that would be poorly formed if it was written using substituted arguments. [Note: access checks are performed as part of the replacement process. - end note] Only invalid types and expressions in the immediate context of a function type and its types of template parameters can lead to failure. [Note: evaluating substituted types and expressions can lead to side effects, such as creating a specialization class template and / or template functions, generating implicitly defined functions, etc. Such side effects are not in a โ€œdirect contextโ€ and can lead to poor program design. - end note]

In your case, creating an instance of underlying_type fails, but not in the immediate context, so it is not a type inference failure, so SFINAE does not apply.

+1
source

You can use SFINAE to prevent the signature of your comparison operators (and therefore an instance of std::underlying_type<T> ) from being created when the corresponding argument is not an enumeration:

 #include <type_traits> template<typename E, typename std::enable_if<std::is_enum<E>::value>::type* = nullptr> bool operator != (E e, typename std::underlying_type<E>::type n) { return static_cast<typename std::underlying_type<E>::type>(e) != n; } template<typename E, typename std::enable_if<std::is_enum<E>::value>::type* = nullptr> bool operator != (typename std::underlying_type<E>::type n, E e) { return static_cast<typename std::underlying_type<E>::type>(e) != n; } 

Here is a living example .

EDIT:

Since VC11 does not seem to support default arguments for function template template parameters, here is an alternative solution:

 template<typename E> typename std::enable_if<std::is_enum<E>::value, bool>::type operator != (E e, typename std::underlying_type<E>::type n) { return static_cast<typename std::underlying_type<E>::type>(e) != n; } template<typename E> typename std::enable_if<std::is_enum<E>::value, bool>::type operator != (typename std::underlying_type<E>::type n, E e) { return static_cast<typename std::underlying_type<E>::type>(e) != n; } 

And a living example , of course.

+4
source

All Articles