Поскольку код, с которым я работаю, компилируется как C или C ++, и все рассматриваемые типы - это typedef (которые легко перенаправляются на классы), мне приходит в голову, что решение C ++ возможно. Следующий пример кода намекает на идею:
#include <inttypes.h>
template <typename outer, typename inner, typename underlying> class arith {
public:
underlying val;
arith(underlying v) : val(v) { }
explicit operator underlying () const { return val; }
outer operator +(const inner &rhs) { return val + rhs.val; }
};
struct narrow;
struct narrow_result : public arith<narrow_result, narrow_result, uint32_t> {
narrow_result(uint32_t v) : arith(v) { }
narrow_result(const narrow &v);
};
struct narrow : public arith<narrow_result, narrow, uint32_t> {
narrow(uint32_t v) : arith(v) { }
narrow(const narrow_result &v) : arith(v.val) { }
};
inline narrow_result::narrow_result(const narrow &v)
: arith(v.val)
{
}
struct wide {
uint64_t val;
wide(uint64_t v) : val(v) { }
wide(const narrow &v) : val(v) { }
operator uint64_t () const { return val; }
wide operator +(const wide &rhs) { return val + rhs.val; }
};
int main()
{
narrow a = 42;
narrow b = 9;
wide c = wide(a) + b;
wide d = a + b; // line 43
narrow e = a + b;
wide f = a; // line 45
narrow g = a + b + b; // line 46
return 0;
}
Здесь GNU C ++ диагностирует только строку 43:
overflow.cc: In function ‘int main()’:
overflow.cc:43:16: error: conversion from ‘narrow_result’ to non-scalar type ‘wide’ requested
Обратите внимание, что неявное преобразование narrow
в wide
все еще разрешено, как видно в строке 45, просто потому, что wide
имеет конструктор преобразования, нацеленный непосредственно на narrow
. Ему просто не хватает одного для narrow_result
.
Строка 46 показывает, что мы можем составлять арифметические операции. Это возможно, потому что narrow
неявно преобразуется в narrow_result
и и наоборот . Однако это неявное преобразование не включается в строку 45; narrow_result
дополнения не конвертируется в narrow
, так что тогда оно может конвертироваться в wide
.
Все это может быть заключено в #ifdef __cplusplus
и при наличии макроса условной отладки, того же макроса, который также позволяет альтернативные определения типов как typedefs для narrow
и wide
. Конечно, в базе шаблонов arith
должны поддерживаться многочисленные другие арифметические операции.