C++ 创建几个相互不兼容的数字类型

C++ 创建几个相互不兼容的数字类型,c++,c++11,C++,C++11,我想创建封装基本数字类型的轻量级类型: struct A { long value; } struct B { long value; } struct C { long value; } ... 因此,我可以对每种类型应用常用的算术运算,并获得预期的结果(与内置的long类型相比,没有任何运行时开销): 现在,如果我只想要一个单一的类型,所有这些都将是简单的;只需为类A定义适当的操作。但是,如果我尝试对类A、B、C…执行相同的操作,很快就会变得单调乏味。。。等等,只是名称不同而已 我知道我可

我想创建封装基本数字类型的轻量级类型:

struct A { long value; }
struct B { long value; }
struct C { long value; }
...
因此,我可以对每种类型应用常用的算术运算,并获得预期的结果(与内置的long类型相比,没有任何运行时开销):

现在,如果我只想要一个单一的类型,所有这些都将是简单的;只需为类A定义适当的操作。但是,如果我尝试对类A、B、C…执行相同的操作,很快就会变得单调乏味。。。等等,只是名称不同而已


我知道我可以使用预处理器宏生成多个具有不同名称的副本。然而,我想知道是否有一种更优雅的方法不使用预处理器,也不需要任何重复的代码。(C++ 11具体的解决方案很好)

如果您的实现在类型上是相同的,可以考虑使用类模板。甚至可以为某些类型专门化模板。只要研究一下这个概念,你就会知道我在说什么。

考虑一下:

#include <iostream>

template <class T,int tag_num=0>
class base{
  public:
    T val;

    base(T val_arg) : val (val_arg) {}

    base<T,tag_num>& operator+(const base<T,tag_num>& a)
    {
      val += a.val;
      return *this;
    }
};

template <class T,int tag_num>
std::ostream& operator<< (std::ostream& s, const base<T,tag_num>& a)
{
    s << a.val;
    return s;
}

typedef base<long,1> my_type_1;
typedef base<long,2> my_type_2;

int main()
{
   my_type_1 v1(1);
   my_type_1 v2(2);
   my_type_1 res = v1 + v2;
   std::cout << res << std::endl;

   my_type_1 r1 = v1;

   my_type_2 v3(3);
   //my_type_1 r2 = v3; // This is a compilation error
   //my_type_1 res2 = v1 + v3; // This is a compilation error
   //std::cout << res2 << std::endl;
   return 0;
}
#包括
模板
阶级基础{
公众:
T值;
base(T val_arg):val(val_arg){}
基本和运算符+(常量基本和a)
{
val+=a.val;
归还*这个;
}
};
模板

std::ostream&operator一种快速的方法是使用定义每个新类型。它将为您实现操作符。当然,这“使用”了预处理器宏,但您不必定义它们。以模板的方式实现算术类型,但是如果您想定义自己的系统(在SI系统之外),则需要更多的参与

如果您想滚动自己的模板类,那么将每个实例化设置为唯一的类型就变得非常重要。有几种方法可以做到这一点。一种方法是为模板提供第二个模板参数(除了“基础类型”)以使实例化唯一。第二个模板参数可以像整数一样简单:

template< class T, int id>
struct strong_typedef {
    // your operators here
};
模板
结构强类型定义{
//这里是你们的接线员
};
但是,您必须对以前使用过的整数进行管理(如果定义分布在不同的位置,这是很困难的)

或者,您可以引入标记类型作为第二个参数:

template< class T, class Tag>
struct strong_typedef// etc...

struct integerA {};
typedef strong_typedef< long, integerA> MyIntegerAType;
template
struct strong_typedef//等。。。
结构整数{};
typedef strong_typedefMyIntegerAType;

一种方法是模板化类,它作为该类的一个实现和类型别名,用于实际类型。这可能如下所示:

namespace detail {
    template<typename Alias>
    struct Implementation {
        //do everything once
    };
}

using A = detail::Implementation<struct DummyA>;
using B = detail::Implementation<struct DummyB>;
using C = detail::Implementation<struct DummyC>;
名称空间详细信息{
模板
结构实现{
//每件事都做一次
};
}
使用A=detail::实现;
使用B=detail::实现;
使用C=detail::实现;

只要每个类都使用不同的类型作为模板参数,每个类型都将是具有相同实现的唯一类型,并且真正的类可以隐藏在用户不应该接触的对象中。

如果您希望它们都具有相同的实现,但都是离散类型,则可以执行类似于
template struct real{/*implement*/}; 使用A=实际值;使用B=实际值。根据您需要的这些类型的数量,您可能能够为您的类使用模板和特殊的类型特征结构。@chris:如果您每次都使用相同的
struct Dummy
,您不是最终得到了兼容的类吗?@MatthieuM.,我很确定它每次都会创建一个新的类。一秒钟。更新:是的,你是对的。它们是一样的,所以每个新的都需要一个不同的名字(cough
DummyA
DummyB
)。@MatthieuM.,啊,问题已经找到了。我想你会喜欢的:为什么第一个模板参数不足以产生唯一的类型?@LightnessRacesinOrbit,OP希望有不同的类型,具有相同的类型,例如,
long
,作为它们的值类型。哦,好的。我没有意识到这一点,因为这太愚蠢了。
只要研究一下这个概念,你就会知道我说的不是一个有用的答案
template< class T, class Tag>
struct strong_typedef// etc...

struct integerA {};
typedef strong_typedef< long, integerA> MyIntegerAType;
namespace detail {
    template<typename Alias>
    struct Implementation {
        //do everything once
    };
}

using A = detail::Implementation<struct DummyA>;
using B = detail::Implementation<struct DummyB>;
using C = detail::Implementation<struct DummyC>;