这个问题是由preferred mechanism to attach a type to a scalar?引起的,但是与度量单位有点偏离了轨道…
假设我要创建一个Float,它的工作原理几乎与float相同(在C#System中不一定是基本的.Float与float几乎完全相同;唯一的区别是一个是类型名,另一个是类型名)是一个关键字).
您可以从struct Float final {float v; } ;.然后可能会增加一堆运算符重载
inline auto operator+(Float lhs, Float rhs) {
return Float { lhs.v + rhs.v };
}
// ... and so on ...
inline bool operator<(Float lhs, Float rhs) {
return lhs.v < rhs.v;
}
// ... etc. ...
现在,我需要能够将Float转换为Double
struct Double final { double v; };
struct Float final { float v;
operator Double() const { return Double { v }; }
};
现在也许我添加了operator&(),以便可以更轻松地与旧版代码进行交互
extern void foo(const float*);
const Float f { 3.14 };
foo(&f);
而不是写foo(& f.v).
清单继续进行……然后,我意识到此代码对于Float和Double是相同的,因此我使用了模板:
template<typename T>
struct Type final { T v; }
using Float = Type<float>;
using Double = Type<double>;
但是现在我意识到T可能不像float那样便宜地复制,所以我必须更改重载
template<typename T>
inline auto make_Type(T&& v) {
return Type<T> { std::forward<T>(v); }
}
template<typename T1, typename T2>
inline auto operator+(const Type<T1>& lhs, const Type<T2>& rhs) {
return make_Type(lhs.v + rhs.v);
}
任意T会带来更多的复杂性.例如,它可能是可移动的,但不可复制.
是否有“规范”的方式来做这样的事情?还是真的开始变得(非常)混乱?以某种方式限制T是否有帮助? (我实际上只需要double,int等,而不需要std :: string或std :: vector< T>).也许有人已经使它适用于一切(差不多?)?
记住,最终我真的想要
template<typename T, typename Tag>
struct TaggedType final
{
typedef Tag tag_type;
typedef T value_type;
value_type value;
};
但不处理Tag似乎是一个很好的简化(并且避免了单位的麻烦).
解决方法:
您正在寻找的库最近在“ Standard C”站点上显示.
查看Tutorial: Emulating strong/opaque typedefs in C++