Информация об изменениях

Сообщение Требуются пояснения от 06.12.2024 21:56

Изменено 06.12.2024 22:17 vdimas

Требуются пояснения
Всем привет, коллега попросил спросить:
https://godbolt.org/z/xhP1b4cn6

  сырцы
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <map>

using namespace std;

namespace umba {
namespace enum_helpers {

// template<typename Integer, std::enable_if_t<std::is_integral<Integer>::value, bool> = true>
// T(Integer) : type(int_t) {}

//----------------------------------------------------------------------------
//! Конвертирует enum в подлежащий тип. Версия для 'честных' enum'ов.
template< typename EnumType, typename std::enable_if< std::is_enum<EnumType>::value, bool>::type = true > inline
typename std::underlying_type< EnumType >::type toUnderlyingType( EnumType flagsVal )
{
typedef typename std::underlying_type< EnumType >::type EnumUnderlyingType;
return (EnumUnderlyingType)flagsVal;
}

//----------------------------------------------------------------------------
//! Конвертирует enum в подлежащий тип. Версия для интегральных типов.
/*! Часто неохота разбираться, является ли значение int'ом, unsigned'ом, или другим интегральным типом,
или же является enum'ом.
*/
template< typename EnumType, typename std::enable_if< (!std::is_enum<EnumType>::value
&& std::is_integral<EnumType>::value
)
, bool>::type = true
> inline
EnumType toUnderlyingType( EnumType flagsVal )
{
return flagsVal;
}

//----------------------------------------------------------------------------
//! Конвертирует в enum из подлежащего типа. Версия для 'честных' enum'ов.
template< typename EnumType, typename std::enable_if< std::is_enum<EnumType>::value, bool
>::type = true > inline
EnumType fromUnderlyingType( typename std::underlying_type< EnumType >::type flagsVal )
{
return (EnumType)flagsVal;
}

//----------------------------------------------------------------------------
//! Конвертирует в enum из подлежащего типа. Версия для интегральных типов.
/*! Часто неохота разбираться, является ли значение int'ом, unsigned'ом, или другим интегральным типом,
или же является enum'ом.
*/
template< typename EnumType, typename std::enable_if< (!std::is_enum<EnumType>::value
&& std::is_integral< EnumType >::value
)
, bool>::type = true
> inline
EnumType fromUnderlyingType( EnumType flagsVal )
{
return flagsVal;
}

//----------------------------------------------------------------------------
template< typename EnumType > inline
bool enumLessImpl(EnumType e1, EnumType e2)
{
typedef typename std::underlying_type< EnumType >::type EnumUnderlyingType;
return (EnumUnderlyingType)e1 < (EnumUnderlyingType)e2;
}

//----------------------------------------------------------------------------
template< typename EnumType > inline
bool enumLessEqualImpl(EnumType e1, EnumType e2)
{
typedef typename std::underlying_type< EnumType >::type EnumUnderlyingType;
return (EnumUnderlyingType)e1 <= (EnumUnderlyingType)e2;
}

//----------------------------------------------------------------------------
template< typename EnumType > inline
bool enumGreaterImpl(EnumType e1, EnumType e2)
{
typedef typename std::underlying_type< EnumType >::type EnumUnderlyingType;
return (EnumUnderlyingType)e1 > (EnumUnderlyingType)e2;
}

//----------------------------------------------------------------------------
template< typename EnumType > inline
bool enumGreaterEqualImpl(EnumType e1, EnumType e2)
{
typedef typename std::underlying_type< EnumType >::type EnumUnderlyingType;
return (EnumUnderlyingType)e1 >= (EnumUnderlyingType)e2;
}


} // namespace enum_helpers
} // namespace umba

//----------------------------------------------------------------------------



//----------------------------------------------------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNARY_OPERATOR_IMPL(EnumType, operatorSign) inline EnumType operator operatorSign( EnumType e ) { return umba::enum_helpers::fromUnderlyingType<EnumType>( operatorSign umba::enum_helpers::toUnderlyingType<EnumType>(e) ); }

//------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType, operatorSign) inline EnumType operator operatorSign( EnumType e1, EnumType e2) { return umba::enum_helpers::fromUnderlyingType<EnumType>( umba::enum_helpers::toUnderlyingType<EnumType>(e1) operatorSign umba::enum_helpers::toUnderlyingType<EnumType>(e2) ); } inline EnumType& operator operatorSign##=( EnumType &e1, EnumType e2) { e1 = e1 operatorSign e2; return e1; }

//------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType, operatorSign) inline EnumType operator operatorSign( EnumType e1, typename std::underlying_type< EnumType >::type e2) { return umba::enum_helpers::fromUnderlyingType<EnumType>( umba::enum_helpers::toUnderlyingType<EnumType>(e1) operatorSign e2 ); } inline EnumType operator operatorSign( typename std::underlying_type< EnumType >::type e1, EnumType e2) { return umba::enum_helpers::fromUnderlyingType<EnumType>( e1 operatorSign umba::enum_helpers::toUnderlyingType<EnumType>(e2) ); } inline EnumType& operator operatorSign##=( EnumType &e1, typename std::underlying_type< EnumType >::type e2) { e1 = e1 operatorSign e2; return e1; }

//------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_ENUM_SHIFT_OPERATOR_IMPL(EnumType, operatorSign) inline EnumType operator operatorSign( EnumType e, unsigned sh ) { return umba::enum_helpers::fromUnderlyingType<EnumType>( umba::enum_helpers::toUnderlyingType<EnumType>(e) operatorSign sh ); } inline EnumType& operator operatorSign##=( EnumType &e, unsigned sh ) { e = e operatorSign sh; return e; }

//----------------------------------------------------------------------------




//----------------------------------------------------------------------------
//! Реализует битовые операции для enum-типа
#define UMBA_ENUM_CLASS_IMPLEMENT_BIT_OPERATORS( EnumType ) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNARY_OPERATOR_IMPL (EnumType,~) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,|) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,&) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,^) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_SHIFT_OPERATOR_IMPL (EnumType,<<) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_SHIFT_OPERATOR_IMPL (EnumType,>>)


//----------------------------------------------------------------------------
//! Реализует битовые операции для enum-типа и подлежащего типа
#define UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_BIT_OPERATORS( EnumType ) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,|) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,&) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,^)


//----------------------------------------------------------------------------
//! Реализует арифметические операции для enum-типа
#define UMBA_ENUM_CLASS_IMPLEMENT_ARITHMETIC_OPERATORS( EnumType ) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNARY_OPERATOR_IMPL (EnumType,+) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNARY_OPERATOR_IMPL (EnumType,-) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,+) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,-) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,*) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,%) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,/)


//----------------------------------------------------------------------------
//! Реализует арифметические операции для enum-типа и подлежащего типа
#define UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_ARITHMETIC_OPERATORS( EnumType ) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,+) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,-) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,*) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,/) UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,%)


//----------------------------------------------------------------------------
//! Реализует операции сравнения больше/меньше для enum-типа
#define UMBA_ENUM_CLASS_IMPLEMENT_RELATION_OPERATORS( EnumType ) inline bool operator< (EnumType e1, EnumType e2) { return umba::enum_helpers::enumLessImpl (e1, e2); } inline bool operator<=(EnumType e1, EnumType e2) { return umba::enum_helpers::enumLessEqualImpl (e1, e2); } inline bool operator> (EnumType e1, EnumType e2) { return umba::enum_helpers::enumGreaterImpl (e1, e2); } inline bool operator>=(EnumType e1, EnumType e2) { return umba::enum_helpers::enumGreaterEqualImpl(e1, e2); }


//----------------------------------------------------------------------------
//! Реализует операции сравнения больше/меньше для enum-типа и подлежащего типа
#define UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_RELATION_OPERATORS( EnumType ) inline bool operator< (EnumType e1, typename std::underlying_type< EnumType >::type e2) { return umba::enum_helpers::enumLessImpl (e1, (EnumType)e2); } inline bool operator<=(EnumType e1, typename std::underlying_type< EnumType >::type e2) { return umba::enum_helpers::enumLessEqualImpl (e1, (EnumType)e2); } inline bool operator> (EnumType e1, typename std::underlying_type< EnumType >::type e2) { return umba::enum_helpers::enumGreaterImpl (e1, (EnumType)e2); } inline bool operator>=(EnumType e1, typename std::underlying_type< EnumType >::type e2) { return umba::enum_helpers::enumGreaterEqualImpl(e1, (EnumType)e2); } inline bool operator< (typename std::underlying_type< EnumType >::type e1, EnumType e2) { return umba::enum_helpers::enumLessImpl ((EnumType)e1, e2); } inline bool operator<=(typename std::underlying_type< EnumType >::type e1, EnumType e2) { return umba::enum_helpers::enumLessEqualImpl ((EnumType)e1, e2); } inline bool operator> (typename std::underlying_type< EnumType >::type e1, EnumType e2) { return umba::enum_helpers::enumGreaterImpl ((EnumType)e1, e2); } inline bool operator>=(typename std::underlying_type< EnumType >::type e1, EnumType e2) { return umba::enum_helpers::enumGreaterEqualImpl((EnumType)e1, e2); }


//----------------------------------------------------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_EQUAL_OPERATORS( EnumType ) template<typename EnumType, typename IntType> inline bool operator==(EnumType e, IntType i) { return umba::enum_helpers::toUnderlyingType(e)==umba::enum_helpers::toUnderlyingType(i); } template<typename EnumType, typename IntType> inline bool operator!=(EnumType e, IntType i) { return umba::enum_helpers::toUnderlyingType(e)!=umba::enum_helpers::toUnderlyingType(i); } inline bool operator!(EnumType e) { return e==0; }

/*
template<typename EnumType, typename IntType> inline bool operator==(IntType i, EnumType e) { return umba::enum_helpers::toUnderlyingType(e)==umba::enum_helpers::toUnderlyingType(i); } template<typename EnumType, typename IntType> inline bool operator!=(IntType i, EnumType e) { return umba::enum_helpers::toUnderlyingType(e)!=umba::enum_helpers::toUnderlyingType(i); }
*/




enum EEE
{
zero,
one,
two

};

enum class CEEE
{
zero,
one,
two

};

enum class MoveFileFlags
{
copyAllowed = 1, //!< If the file is to be moved to a different volume, the function simulates the move by using the CopyFile and DeleteFile functions.
replaceExisting = 2, //!< If a file named lpNewFileName exists, the function replaces its contents with the contents of the lpExistingFileName file
overwrite = 2, //!< Same as replaceExisting
writeThrough = 4 //!< The function does not return until the file is actually moved on the disk. Setting this value guarantees that a move performed as a copy and delete operation is flushed to disk before the function returns. The flush occurs at the end of the copy operation.
};


UMBA_ENUM_CLASS_IMPLEMENT_BIT_OPERATORS(MoveFileFlags)
UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_BIT_OPERATORS(MoveFileFlags)
UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_EQUAL_OPERATORS(MoveFileFlags)

inline
bool isKindOfName(const std::unordered_set<std::string>& s, const std::string &name)
{
//return s.find(name)!=s.end();
return true;
}



int main()
{
using namespace umba::enum_helpers;
cout << "val of EEE::one: " << toUnderlyingType(one) << "\n";
cout << "val of EEE::two: " << toUnderlyingType(two) << "\n";

cout << "val of CEEE::one: " << toUnderlyingType(CEEE::one) << "\n";
cout << "val of CEEE::two: " << toUnderlyingType(CEEE::two) << "\n";

cout << "val of 1: " << toUnderlyingType(1) << "\n";
cout << "val of 2: " << toUnderlyingType(2) << "\n";

cout << "val of copyAllowed : " << toUnderlyingType(MoveFileFlags::copyAllowed) << "\n";
cout << "val of replaceExisting: " << toUnderlyingType(MoveFileFlags::replaceExisting) << "\n";

cout << "MoveFileFlags::replaceExisting==1: " << (MoveFileFlags::replaceExisting==1 ? "true" : "false") << "\n";

MoveFileFlags flags = MoveFileFlags::replaceExisting;

}


строка 321 — работает
если её раскоментировать, и закоментировать следующую — гцц не компилит

После поверхностного вникания я предложил добавить недостающий вариант

template< typename EnumType, typename std::enable_if< (!std::is_enum<EnumType>::value
                                                    &&  !std::is_integral<EnumType>::value
                                                      )
                                                    , bool>::type = true
                                                    > inline
int toUnderlyingType( EnumType flagsVal )
{
    return 0;
}


И оно ожидаемо сработало.
код подцепляет этот вариант, можно добавить в его тело static_assert
template< typename EnumType, typename std::enable_if< (!std::is_enum<EnumType>::value
                                                    &&  !std::is_integral<EnumType>::value
                                                      )
                                                    , bool>::type bb = false
                                                    > inline
int toUnderlyingType( EnumType flagsVal )
{
    static_assert(bb);
    return 0;
}


Подцепляет, ИМХО, из этих строчек
template<typename EnumType, typename IntType> inline                                               \            
bool operator==(EnumType e, IntType i)
Требуются пояснения
Всем привет, коллега попросил спросить:
https://godbolt.org/z/xhP1b4cn6

  сырцы
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <map>

using namespace std;

namespace umba {
namespace enum_helpers {

// template<typename Integer,         std::enable_if_t<std::is_integral<Integer>::value, bool> = true>
//     T(Integer) : type(int_t) {}

//----------------------------------------------------------------------------
//! Конвертирует enum в подлежащий тип. Версия для 'честных' enum'ов.
template< typename EnumType, typename std::enable_if< std::is_enum<EnumType>::value, bool>::type = true > inline
typename std::underlying_type< EnumType >::type toUnderlyingType( EnumType flagsVal )
{
    typedef typename std::underlying_type< EnumType >::type    EnumUnderlyingType;
    return (EnumUnderlyingType)flagsVal;
}

//----------------------------------------------------------------------------
//! Конвертирует enum в подлежащий тип. Версия для интегральных типов.
/*! Часто неохота разбираться, является ли значение int'ом, unsigned'ом, или другим интегральным типом,
    или же является enum'ом.
 */
template< typename EnumType, typename std::enable_if< (!std::is_enum<EnumType>::value
                                                    &&  std::is_integral<EnumType>::value
                                                      )
                                                    , bool>::type = true
                                                    > inline
EnumType toUnderlyingType( EnumType flagsVal )
{
    return flagsVal;
}

//----------------------------------------------------------------------------
//! Конвертирует в enum из подлежащего типа. Версия для 'честных' enum'ов.
template< typename EnumType, typename std::enable_if< std::is_enum<EnumType>::value, bool
                                                    >::type = true > inline
EnumType fromUnderlyingType( typename std::underlying_type< EnumType >::type flagsVal )
{
    return (EnumType)flagsVal;
}

//----------------------------------------------------------------------------
//! Конвертирует в enum из подлежащего типа. Версия для интегральных типов.
/*! Часто неохота разбираться, является ли значение int'ом, unsigned'ом, или другим интегральным типом,
    или же является enum'ом.
 */
template< typename EnumType, typename std::enable_if< (!std::is_enum<EnumType>::value 
                                                    &&  std::is_integral< EnumType >::value
                                                      )
                                                    , bool>::type = true 
                                                    > inline
EnumType fromUnderlyingType( EnumType flagsVal )
{
    return flagsVal;
}

//----------------------------------------------------------------------------
template< typename EnumType > inline
bool enumLessImpl(EnumType e1, EnumType e2)
{
    typedef typename std::underlying_type< EnumType >::type    EnumUnderlyingType;
    return (EnumUnderlyingType)e1 < (EnumUnderlyingType)e2;
}

//----------------------------------------------------------------------------
template< typename EnumType > inline
bool enumLessEqualImpl(EnumType e1, EnumType e2)
{
    typedef typename std::underlying_type< EnumType >::type    EnumUnderlyingType;
    return (EnumUnderlyingType)e1 <= (EnumUnderlyingType)e2;
}

//----------------------------------------------------------------------------
template< typename EnumType > inline
bool enumGreaterImpl(EnumType e1, EnumType e2)
{
    typedef typename std::underlying_type< EnumType >::type    EnumUnderlyingType;
    return (EnumUnderlyingType)e1 > (EnumUnderlyingType)e2;
}

//----------------------------------------------------------------------------
template< typename EnumType > inline
bool enumGreaterEqualImpl(EnumType e1, EnumType e2)
{
    typedef typename std::underlying_type< EnumType >::type    EnumUnderlyingType;
    return (EnumUnderlyingType)e1 >= (EnumUnderlyingType)e2;
}


} // namespace enum_helpers
} // namespace umba

//----------------------------------------------------------------------------



//----------------------------------------------------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNARY_OPERATOR_IMPL(EnumType, operatorSign)                                          inline                                                                                                          EnumType operator operatorSign( EnumType e )                                                                   {                                                                                                                   return umba::enum_helpers::fromUnderlyingType<EnumType>(                                                                                   operatorSign                                                                                                    umba::enum_helpers::toUnderlyingType<EnumType>(e)                                    );                                                                                                          }

//------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType, operatorSign)                                         inline                                                                                                          EnumType operator operatorSign( EnumType e1, EnumType e2)                                                      {                                                                                                                   return umba::enum_helpers::fromUnderlyingType<EnumType>(                                                                                   umba::enum_helpers::toUnderlyingType<EnumType>(e1)                                                              operatorSign                                                                                                    umba::enum_helpers::toUnderlyingType<EnumType>(e2)                                   );                                                                                                          }                                                                                                               inline                                                                                                          EnumType& operator operatorSign##=( EnumType &e1, EnumType e2)                                                 {                                                                                                                   e1 = e1 operatorSign e2;                                                                                        return e1;                                                                                                  }

//------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType, operatorSign)                         inline                                                                                                          EnumType operator operatorSign( EnumType e1, typename std::underlying_type< EnumType >::type e2)               {                                                                                                                   return umba::enum_helpers::fromUnderlyingType<EnumType>(                                                                                   umba::enum_helpers::toUnderlyingType<EnumType>(e1)                                                              operatorSign                                                                                                    e2                                                                                   );                                                                                                          }                                                                                                               inline                                                                                                          EnumType operator operatorSign( typename std::underlying_type< EnumType >::type e1, EnumType e2)               {                                                                                                                   return umba::enum_helpers::fromUnderlyingType<EnumType>(                                                                                   e1                                                                                                              operatorSign                                                                                                    umba::enum_helpers::toUnderlyingType<EnumType>(e2)                                   );                                                                                                          }                                                                                                               inline                                                                                                          EnumType& operator operatorSign##=( EnumType &e1, typename std::underlying_type< EnumType >::type e2)             {                                                                                                                   e1 = e1 operatorSign e2;                                                                                        return e1;                                                                                                  }

//------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_ENUM_SHIFT_OPERATOR_IMPL(EnumType, operatorSign)                                          inline                                                                                                          EnumType operator operatorSign( EnumType e, unsigned sh )                                                      {                                                                                                                   return umba::enum_helpers::fromUnderlyingType<EnumType>(                                                                                   umba::enum_helpers::toUnderlyingType<EnumType>(e)                                                               operatorSign                                                                                                    sh                                                                                   );                                                                                                          }                                                                                                               inline                                                                                                          EnumType& operator operatorSign##=( EnumType &e, unsigned sh )                                                 {                                                                                                                   e = e operatorSign sh;                                                                                          return e;                                                                                                   }

//----------------------------------------------------------------------------




//----------------------------------------------------------------------------
//! Реализует битовые операции для enum-типа
#define UMBA_ENUM_CLASS_IMPLEMENT_BIT_OPERATORS( EnumType )                                                                  UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNARY_OPERATOR_IMPL (EnumType,~)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,|)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,&)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,^)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_SHIFT_OPERATOR_IMPL (EnumType,<<)                                                UMBA_ENUM_CLASS_IMPLEMENT_ENUM_SHIFT_OPERATOR_IMPL (EnumType,>>)


//----------------------------------------------------------------------------
//! Реализует битовые операции для enum-типа и подлежащего типа
#define UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_BIT_OPERATORS( EnumType )                                                   UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,|)                                  UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,&)                                  UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,^)


//----------------------------------------------------------------------------
//! Реализует арифметические операции для enum-типа
#define UMBA_ENUM_CLASS_IMPLEMENT_ARITHMETIC_OPERATORS( EnumType )                                                           UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNARY_OPERATOR_IMPL (EnumType,+)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNARY_OPERATOR_IMPL (EnumType,-)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,+)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,-)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,*)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,%)                                                 UMBA_ENUM_CLASS_IMPLEMENT_ENUM_BINARY_OPERATOR_IMPL(EnumType,/)


//----------------------------------------------------------------------------
//! Реализует арифметические операции для enum-типа и подлежащего типа
#define UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_ARITHMETIC_OPERATORS( EnumType )                                            UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,+)                                  UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,-)                                  UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,*)                                  UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,/)                                  UMBA_ENUM_CLASS_IMPLEMENT_ENUM_UNDERLYING_TYPE_BINARY_OPERATOR_IMPL(EnumType,%)


//----------------------------------------------------------------------------
//! Реализует операции сравнения больше/меньше для enum-типа
#define UMBA_ENUM_CLASS_IMPLEMENT_RELATION_OPERATORS( EnumType )                                                                                                                                                                                                     inline bool operator< (EnumType e1, EnumType e2) { return umba::enum_helpers::enumLessImpl        (e1, e2); }               inline bool operator<=(EnumType e1, EnumType e2) { return umba::enum_helpers::enumLessEqualImpl   (e1, e2); }               inline bool operator> (EnumType e1, EnumType e2) { return umba::enum_helpers::enumGreaterImpl     (e1, e2); }               inline bool operator>=(EnumType e1, EnumType e2) { return umba::enum_helpers::enumGreaterEqualImpl(e1, e2); }


//----------------------------------------------------------------------------
//! Реализует операции сравнения больше/меньше для enum-типа и подлежащего типа
#define UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_RELATION_OPERATORS( EnumType )                                                                                                                                                                                      inline bool operator< (EnumType e1, typename std::underlying_type< EnumType >::type e2) { return umba::enum_helpers::enumLessImpl        (e1, (EnumType)e2); }              inline bool operator<=(EnumType e1, typename std::underlying_type< EnumType >::type e2) { return umba::enum_helpers::enumLessEqualImpl   (e1, (EnumType)e2); }              inline bool operator> (EnumType e1, typename std::underlying_type< EnumType >::type e2) { return umba::enum_helpers::enumGreaterImpl     (e1, (EnumType)e2); }              inline bool operator>=(EnumType e1, typename std::underlying_type< EnumType >::type e2) { return umba::enum_helpers::enumGreaterEqualImpl(e1, (EnumType)e2); }                                                                                                                                          inline bool operator< (typename std::underlying_type< EnumType >::type e1, EnumType e2) { return umba::enum_helpers::enumLessImpl        ((EnumType)e1, e2); }              inline bool operator<=(typename std::underlying_type< EnumType >::type e1, EnumType e2) { return umba::enum_helpers::enumLessEqualImpl   ((EnumType)e1, e2); }              inline bool operator> (typename std::underlying_type< EnumType >::type e1, EnumType e2) { return umba::enum_helpers::enumGreaterImpl     ((EnumType)e1, e2); }              inline bool operator>=(typename std::underlying_type< EnumType >::type e1, EnumType e2) { return umba::enum_helpers::enumGreaterEqualImpl((EnumType)e1, e2); }


//----------------------------------------------------------------------------
#define UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_EQUAL_OPERATORS( EnumType )                                                                                                                                                                template<typename EnumType, typename IntType> inline                                                            bool operator==(EnumType e, IntType i)                                                                          {                                                                                                                   return umba::enum_helpers::toUnderlyingType(e)==umba::enum_helpers::toUnderlyingType(i);                    }                                                                                                                                                                                                                               template<typename EnumType, typename IntType> inline                                                            bool operator!=(EnumType e, IntType i)                                                                          {                                                                                                                   return umba::enum_helpers::toUnderlyingType(e)!=umba::enum_helpers::toUnderlyingType(i);                    }                                                                                                                                                                                                                               inline                                                                                                          bool operator!(EnumType e)                                                                                      {                                                                                                                   return e==0;                                                                                                }

/*
             template<typename EnumType, typename IntType> inline                                                            bool operator==(IntType i, EnumType e)                                                                          {                                                                                                                   return umba::enum_helpers::toUnderlyingType(e)==umba::enum_helpers::toUnderlyingType(i);                    }                                                                                                                                                                                                                               template<typename EnumType, typename IntType> inline                                                            bool operator!=(IntType i, EnumType e)                                                                          {                                                                                                                   return umba::enum_helpers::toUnderlyingType(e)!=umba::enum_helpers::toUnderlyingType(i);                    }                                                                                                  
*/




enum EEE
{
    zero,
    one,
    two

};

enum class CEEE
{
    zero,
    one,
    two

};

enum class MoveFileFlags
{
    copyAllowed     = 1, //!< If the file is to be moved to a different volume, the function simulates the move by using the CopyFile and DeleteFile functions.
    replaceExisting = 2, //!< If a file named lpNewFileName exists, the function replaces its contents with the contents of the lpExistingFileName file
    overwrite       = 2, //!< Same as replaceExisting
    writeThrough    = 4  //!< The function does not return until the file is actually moved on the disk. Setting this value guarantees that a move performed as a copy and delete operation is flushed to disk before the function returns. The flush occurs at the end of the copy operation.
};


UMBA_ENUM_CLASS_IMPLEMENT_BIT_OPERATORS(MoveFileFlags)
UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_BIT_OPERATORS(MoveFileFlags)
UMBA_ENUM_CLASS_IMPLEMENT_UNDERLYING_TYPE_EQUAL_OPERATORS(MoveFileFlags)

inline
bool isKindOfName(const std::unordered_set<std::string>& s, const std::string &name)
{
    //return s.find(name)!=s.end();
    return true;
}



int main()
{
    using namespace umba::enum_helpers;
    cout << "val of EEE::one: " << toUnderlyingType(one) << "\n";
    cout << "val of EEE::two: " << toUnderlyingType(two) << "\n";

    cout << "val of CEEE::one: " << toUnderlyingType(CEEE::one) << "\n";
    cout << "val of CEEE::two: " << toUnderlyingType(CEEE::two) << "\n";

    cout << "val of 1: " << toUnderlyingType(1) << "\n";
    cout << "val of 2: " << toUnderlyingType(2) << "\n";

    cout << "val of copyAllowed    : " << toUnderlyingType(MoveFileFlags::copyAllowed) << "\n";
    cout << "val of replaceExisting: " << toUnderlyingType(MoveFileFlags::replaceExisting) << "\n";

    cout << "MoveFileFlags::replaceExisting==1: " << (MoveFileFlags::replaceExisting==1 ? "true" : "false") << "\n";

    MoveFileFlags flags = MoveFileFlags::replaceExisting;

}


строка 321 — работает
если её раскоментировать, и закоментировать следующую — гцц не компилит

После поверхностного вникания я предложил добавить недостающий вариант

template< typename EnumType, typename std::enable_if< (!std::is_enum<EnumType>::value
                                                    &&  !std::is_integral<EnumType>::value
                                                      )
                                                    , bool>::type = true
                                                    > inline
int toUnderlyingType( EnumType flagsVal )
{
    return 0;
}


И оно ожидаемо сработало.
код подцепляет этот вариант, можно добавить в его тело static_assert
template< typename EnumType, typename std::enable_if< (!std::is_enum<EnumType>::value
                                                    &&  !std::is_integral<EnumType>::value
                                                      )
                                                    , bool>::type bb = false
                                                    > inline
int toUnderlyingType( EnumType flagsVal )
{
    static_assert(bb);
    return 0;
}


Подцепляет, ИМХО, из этих строчек
template<typename EnumType, typename IntType> inline                                               \            
bool operator==(EnumType e, IntType i)