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

后端 未结 2 1446
轻奢々
轻奢々 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 <type_traits>  // std::underlying_type
    #include <utility>      // 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<Enum>(), void >
                >
            inline auto operator+( Enum const a, Enum const b )
                -> Enum
            {
                using Integral = underlying_type_t<Enum>;
                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 <iostream>
    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<my::Foo>() << endl;     // true
        cout << "Bar -> " << cppx::is_typed_integer<my::Bar>() << endl;     // false
    
        auto x2 = x + x;
        cout << int( x2 ) << endl;
    #ifdef TRY_BAR
        auto y2 = y + y;            //! Not an arithmetic type.
        (void) y2;
    #endif
    }
    
    0 讨论(0)
  • 2021-01-23 15:14

    A typedef or using statement will not introduce a new type.

    To get a new type you need to define one:

    struct foo { int x; };
    struct bar { int x; };
    
    int main()
    {
        //typedef int foo;
        //typedef int bar;
        foo x{5};
        bar y{7};
        int z = x + y;  // now doesn't compile, wants an operator+() defined  
        return 0;
    }
    

    In the above example we take advantage of aggregate initialization to allow for the use of the structs in this way.

    0 讨论(0)
提交回复
热议问题