如何创建一个行为与其他类型相似的类型?

时间:2016-12-01 14:40:26

标签: c++ templates types

这个问题是由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)

然后列表继续......然后,我意识到FloatDouble的代码是相同的,所以我使用模板:

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是否有帮助? (我真的只需要doubleint等,而不是std::stringstd::vector<T>。也许有人已经让它(或几乎?)一切都运行良好?

请记住,最终我真的想要

template<typename T, typename Tag>
struct TaggedType final
{
typedef Tag tag_type;
typedef T value_type;
value_type value;
};

但不处理Tag似乎是一个很好的简化(并避免单位的兔子洞)。

1 个答案:

答案 0 :(得分:1)

您正在寻找的图书馆最近在“标准C ++”网站上展示。

请参阅Tutorial: Emulating strong/opaque typedefs in C++