Как я должен боксировать целочисленные типы в C ++?

Предположим, мой код имеет

using foo = int32_t;

где-то и

using bar = int32_t;

тогда по какой-то причине мне нужно различать этот тип и другие int32_ts (и их псевдонимы). Но — я все еще хочу, чтобы они вели себя так же, как int32_ts.

Теперь я могу написать:

struct foo { int32_t value; }
struct bar { int32_t value; }

который различает типы. Но — эти структуры не ведут себя как intс на всех; Я даже не могу сравнить fooдруг другу! (Ну, не раньше C ++ 20 в любом случае)

поскольку int32_t это не класс, я не может делать:

struct foo : public int32_t { }

хотя это дало бы мне именно то, что мне нужно.

Таким образом, мне кажется, что я хочу добиться «упаковки» (а-ля Java, C # и т. Д.) Простых целых чисел в классы, а об остальном позаботится наследование.

Конечно, можно вычеркнуть множество шаблонов и реализовать все соответствующие операторы для целых чисел: присваивание, сравнение, арифметика и т. Д. Но, вы знаете, DRY!

Если бы я мог переопределить точку оператора, это могло бы сэкономить мне весь код, но это предложение застряло и не похоже, что оно куда-нибудь пойдет в ближайшее время.

Так есть ли что-то еще, что я мог бы использовать, чтобы избежать всего этого шаблона?

0

Решение

Есть один способ, которым я пытался (но не тщательно проверял), чтобы избежать повторения шаблона. Он использует шаблоны, чтобы легко создать новый тип, просто указав другой номер в качестве параметра шаблона. Результирующий тип может быть псевдонимом типа, чтобы избавиться от уродливого определения шаблона:

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';
}

Вы создаете шаблон один раз как шаблон класса а также иллюстрировать примерами это как разные типы просто поставляя уникальный индекс в качестве первого параметра шаблона.

2

Другие решения

Сильные typedefs

Несколько комментариев на сайте и вне его (в том числе @HenriMenke) подняли термин «сильный typedef». С ++ typedefs «слабые» — они определяют неразличимые псевдонимы. Сильная typedef нового типа T как типа U заставит T вести себя как U, не имея типа U.

То, что вы хотите сделать, это определить две «сильные определения типа» foo и из bar как инт.

Есть, по крайней мере, две распространенные библиотеки strong-typedef, ну, я думаю, вы могли бы сказать:

0

По вопросам рекламы [email protected]