How to create a strong typedef in C++(11) without an external library?

后端 未结 2 1448
轻奢々
轻奢々 2021-01-23 14:37

So, I know you can alias types with the following:
typedef int *intPtr
But the C++ compiler can\'t differentiate between them:

typedef int         


        
2条回答
  •  时光取名叫无心
    2021-01-23 14:59

    One way to create a type that acts like a new integral type is to use a based enum. But beware: an enum is not formally an integral type. It's only its base type that is an integral type.

    Also, a heads-up: I've never found this useful enough to do it.

    That said, it can go like this:

    #include   // std::underlying_type
    #include       // std::enable_if
    
    //----------------------------------------- Machinery:
    
    namespace cppx {
        using std::enable_if_t;
        using std::underlying_type_t;
    
        namespace impl {
            inline constexpr auto is_a_typed_integer( ... ) -> bool { return false; }
        }  // namespace impl
    
        template< class Type >
        inline constexpr auto is_typed_integer()
            -> bool
        {
            using impl::is_a_typed_integer;
            return is_a_typed_integer( Type() );
        }
    
        namespace enum_arithmetic {
            template< class Enum
                , class Enabled_ = enable_if_t< is_typed_integer(), void >
                >
            inline auto operator+( Enum const a, Enum const b )
                -> Enum
            {
                using Integral = underlying_type_t;
                return Enum( Integral( a ) + Integral( b ) );
            }
        }
    
    }  // namespace cppx
    
    
    //----------------------------------------- Usage:
    
    namespace my {
        using cppx::enum_arithmetic::operator+;  // Makes it accessible via ADL.
    
        enum class Foo: int {};
        inline constexpr auto is_a_typed_integer( Foo ) -> bool { return true; }
    
        enum class Bar: int {};
    }  // namespace my
    
    
    //----------------------------------------- Test:
    
    #include 
    using namespace std;
    auto main() -> int
    {
        auto x = my::Foo( 5 );
        auto y = my::Bar( 7 );
        (void) y;
    
    #ifdef TRY_CONVERSION
        int z = x + y;              //! No implicit conversion.
        (void) z;
    #endif
    
        cout << boolalpha;
        cout << "Foo -> " << cppx::is_typed_integer() << endl;     // true
        cout << "Bar -> " << cppx::is_typed_integer() << endl;     // false
    
        auto x2 = x + x;
        cout << int( x2 ) << endl;
    #ifdef TRY_BAR
        auto y2 = y + y;            //! Not an arithmetic type.
        (void) y2;
    #endif
    }
    

提交回复
热议问题