如何在C ++中装箱整数类型?

时间:2018-11-15 21:42:56

标签: c++ integer class-design idiomatic

假设我的代码有

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,那么可以节省我所有的代码,但是该建议被搁置了,看起来不会很快就解决了。

那么我还有什么可以避免所有这些样板的东西?

2 个答案:

答案 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)

强大的typedef

几个现场和非现场评论(包括@HenriMenke)提出了“ strong typedef”一词。 C ++ typedef是“弱”的-它们定义了难以区分的别名。新的T类型的强类型定义(如U类型)会使T的行为像U,而没有U类型。

您要做的是将foobar的两个“ strong typedef”定义为int。

至少有两个常见的strong-typedef,嗯,我猜你可以说: