创建几个相互不兼容的数字类型
Creating several mutually incompatible numerical types
我想创建封装基元数字类型的轻量级类型:
struct A { long value; }
struct B { long value; }
struct C { long value; }
...
这样我就可以将通常的算术运算应用于每种类型,并获得预期的结果(与内置的long类型相比,没有任何运行时开销):
A a1 {10};
A a2 {20};
A a3 = a1 + a2:
++a3;
std::cout << a3; // prints "31"
...
但是,我不希望在不同类型之间进行任何(自动)转换,也不希望允许任何混合不同类型的算术运算。例如,以下代码应该而不是编译:
A a1 {10};
A a2 {20};
B b3 = a1 + a2: // error, cannot convert A to B
a2 += b3; // error, A::operator+=(B) does not exist
...
现在,如果我只想要一种类型,所有这些都会很简单;只需为类A定义适当的操作即可。然而,如果我试图对类A、B、C。。。等等,它们只是在名称上不同。
我知道我可以使用预处理器宏生成多个不同名称的副本。然而,我想知道是否有一种更优雅的方法不使用预处理器,也不需要任何重复的代码。(C++11特定的解决方案很好。)
一种方法是一个模板化的类,它充当该类的一个实现和真实类型的类型别名。这可能看起来如下:
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>;
只要每个都使用不同的类型作为模板参数,每个都将是具有相同实现的唯一类型,并且真实的类可以隐藏在用户不应该接触的地方。
一种快速的方法是使用BOOstrongTRONG_TYPEDEF定义每个新类型。它将为您实现运算符。当然,这"使用"了预处理器宏,但您不必定义它们。Boost.units以模板的方式实现算术类型,但如果您想定义自己的系统(在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;
只需考虑:
#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;
}
如果不同类型的实现相同,则可以考虑使用类模板。甚至你也可以为某些类型专门化一个模板。只要研究一下这个概念,你就会知道我在说什么。
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- 字符类型转换不兼容
- Qt:如何使不兼容的发送方/接收方参数兼容?
- 视觉工作室 2017;启用 /permissive 时,类型 "const wchar_t *" 的参数与类型 "PWSTR" 的参数不兼容
- 使用不兼容的分配器复制分配无序列图
- C++输出奇怪的字符而不是数字 (Windows)
- 为什么strlen(s)与s的大小不同,为什么cout-char显示的是字符而不是数字
- 类型为 "int*" 的参数与 C++ 中错误类型"int**"参数不兼容
- 该对象具有与成员函数不兼容的类型限定符.为什么会出现此错误?
- 我正在尝试将表的地址传递给要在另一个函数中使用的指针,但得到不兼容的指针类型
- 为什么范围算法与 std 的迭代器不兼容?
- Winpcap Findalldevs const char * 与 char * 不兼容
- 为什么 sf::Text 显示点而不是数字?
- 是否有一个 std::set 函数来确定不超过数字 x 的最大元素?
- C++ 类型的参数与 void (__cdecl*)(void) 类型的参数不兼容,当调用 std::atexit()
- 将"std::string {aka std::basic_string}"赋值中的不兼容类型<char>
- 如何在C++中停止调用不兼容的方法?
- OPENCL 警告:不兼容的指针类型将'float __global[16]'传递给类型为 '__global float4 的参数 *
- 函数范围的静态变量如何导致与共享库中函数代码的未来使用不兼容
- 创建几个相互不兼容的数字类型