这个问题是由preferred mechanism to attach a type to a scalar?推动的,但这与计量单位有点偏离......
让我们说我想创建一个Float
,它几乎就像float
一样(这不一定是激进的,在C#System.Float
几乎是< em>完全与float
相同;唯一的区别是一个是类型名称而另一个是关键字。“
您可以使用struct Float final { float v; };
开始简单。然后可能会添加一堆operator
重载
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
会有更多并发症;例如,它可能是可移动的,但不可复制。
是否有&#34;规范&#34;做这样的事情的方法?或者它真的开始(非常)凌乱?以某种方式限制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
似乎是一个很好的简化(并避免单位的兔子洞)。