【问题标题】:How to create a strong typedef in C++(11) without an external library?如何在没有外部库的情况下在 C++(11) 中创建强类型定义?
【发布时间】:2016-04-11 11:45:53
【问题描述】:

所以,我知道您可以使用以下类型对类型进行别名:
typedef int *intPtr
但是 C++ 编译器无法区分它们:

typedef int foo  
typedef int bar  
foo x = 5;  
bar y = 7;  
int z = x + y;  // checks out  

我知道 C++ 没有没有一些诡计 (How can I create a new primitive type using C++11 style strong typedefs?),但我发现所说的诡计难以阅读和理解。
我发现唯一可行的解​​决方案是使用 Boost 库,但我对使用外部库有strong厌恶。
那么,是否有任何易于理解的技巧来制作强大的 typedef?

【问题讨论】:

  • 为什么不为每个类创建一个?
  • “我非常讨厌使用外部库”——为什么?这听起来像是“这里不发明”综合症的严重案例。重用已经编写(更不用说经过审查和测试)的代码可以节省您解决尚未解决的问题的时间,而不是重复一百万次重新发明轮子。
  • 您是否正在尝试解决某个特定问题?
  • C++ 中没有强类型定义。

标签: c++ typedef


【解决方案1】:

typedefusing 声明 will not introduce a new type

要获得一个新类型,您需要定义一个:

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;
}

在上面的示例中,我们利用aggregate initialization 来允许以这种方式使用structs

【讨论】:

    【解决方案2】:

    创建一个作用类似于新整数类型的类型的一种方法是使用基于enum。但请注意:enum 不是正式的整数类型。只有它的基类型是整数类型。

    另外,请注意:我从来没有发现这足以做到这一点。

    也就是说,它可以是这样的:

    #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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 1970-01-01
      • 1970-01-01
      • 2010-12-28
      • 1970-01-01
      • 2012-06-29
      • 1970-01-01
      相关资源
      最近更新 更多