假设我的代码有
using foo = int32_t;
某个地方,和
using bar = int32_t;
然后,由于某种原因,我需要区分此类型和其他int32_t
(及其别名)。但是-我仍然希望它们的行为像int32_t
一样。
现在,我可以写:
struct foo { int32_t value; }
struct bar { int32_t value; }
区分类型。但是-这些结构的行为完全不像int
;我什至无法将foo
相互比较! (好吧,反正不是在C ++ 20之前)
由于int32_t
不是课程,我不能做:
struct foo : public int32_t { }
尽管这将完全满足我的需求。
所以看来我想要实现的是将普通整数“装箱”(Java Java,C#等)到类中,其余的将通过继承来处理。
当然可以脱颖而出,并实现所有相关的整数运算符:赋值,比较,算术等。但是,DRY!
如果我可以override operator dot,那么可以节省我所有的代码,但是该建议被搁置了,看起来不会很快就解决了。
那么我还有什么可以避免所有这些样板的东西?
答案 0 :(得分:2)
我尝试过一种方法(但未经严格测试),以避免重复样板。它只需提供一个不同的数字作为模板参数,就可以使用模板轻松地创建新类型。可以对结果类型进行别名化处理,以摆脱丑陋的模板定义:
namespace alt {
template<std::size_t TypeId, typename Number>
class typed_number
{
public:
explicit typed_number(Number n): n(n) {}
typed_number(typed_number const& tn): n(tn.n) {}
typed_number& operator= (typed_number const& tn) { this->n = tn.n; return *this; }
typed_number& operator+=(typed_number const& tn) { this->n += tn.n; return *this; }
typed_number& operator-=(typed_number const& tn) { this->n -= tn.n; return *this; }
typed_number& operator*=(typed_number const& tn) { this->n *= tn.n; return *this; }
typed_number& operator/=(typed_number const& tn) { this->n /= tn.n; return *this; }
explicit operator Number() const { return n; }
bool operator==(typed_number tn) const { return this->n == tn; }
bool operator!=(typed_number tn) const { return this->n != tn; }
bool operator<=(typed_number tn) const { return this->n <= tn; }
bool operator>=(typed_number tn) const { return this->n >= tn; }
bool operator< (typed_number tn) const { return this->n < tn; }
bool operator> (typed_number tn) const { return this->n > tn; }
typed_number operator+(typed_number const& tn) const { return typed_number(this->n + tn.n); }
typed_number operator-(typed_number const& tn) const { return typed_number(this->n - tn.n); }
typed_number operator*(typed_number const& tn) const { return typed_number(this->n * tn.n); }
typed_number operator/(typed_number const& tn) const { return typed_number(this->n / tn.n); }
friend std::ostream& operator<<(std::ostream& os, typed_number<TypeId, Number> n)
{ return os << n.n; }
friend std::istream& operator>>(std::istream& is, typed_number<TypeId, Number>& n)
{ return is >> n.n; }
private:
Number n;
};
} // namespace alt
// give each incompatible type a different index
using dollars = alt::typed_number<0, int>;
using cents = alt::typed_number<1, int>;
int main()
{
auto d1 = dollars(5);
auto d2 = dollars(9);
auto d3 = d1 + d2;
std::cout << d1 << " + " << d2 << " = " << d3 << '\n';
}
只需将模板提供类型,即可将其创建为模板类,然后实例化为不同的类型 唯一索引作为第一个模板参数。
答案 1 :(得分:0)
几个现场和非现场评论(包括@HenriMenke)提出了“ strong typedef”一词。 C ++ typedef是“弱”的-它们定义了难以区分的别名。新的T类型的强类型定义(如U类型)会使T的行为像U,而没有U类型。
您要做的是将foo
和bar
的两个“ strong typedef”定义为int。
至少有两个常见的strong-typedef,嗯,我猜你可以说:
type_safe
(repo on GitHub):提供ts::integer<T>
strong typdef
,它较旧且基于宏