C++ C++;:将基类型完美透明地包装到类中?

C++ C++;:将基类型完美透明地包装到类中?,c++,c++11,type-conversion,ambiguous,C++,C++11,Type Conversion,Ambiguous,我正在尝试开发一个类,它完美地包装了基类型,这样人们就可以像正常情况一样使用它们,同时也可以扩展它们/添加新功能(c++11/c++14/etc很好)。到目前为止我还没有成功。下面是我遇到的一个例子(这里我只实现了plus操作符,但我最终会实现它们): 模板 N类 { 公众: N(){}; N(int _var):var(_var){}; 模板 N运算符+(常数N&i)常数 {返回var+i;}; //#定义转换(x)模板::类型>运算符x()常量{return var;}; #定义转换(x)运

我正在尝试开发一个类,它完美地包装了基类型,这样人们就可以像正常情况一样使用它们,同时也可以扩展它们/添加新功能(c++11/c++14/etc很好)。到目前为止我还没有成功。下面是我遇到的一个例子(这里我只实现了plus操作符,但我最终会实现它们):

模板
N类
{
公众:
N(){};
N(int _var):var(_var){};
模板
N运算符+(常数N&i)常数
{返回var+i;};
//#定义转换(x)模板::类型>运算符x()常量{return var;};
#定义转换(x)运算符x()常量{return var;};
转换(bool);
转换(字符);
转换(无符号字符);
转换(短);
转换(无符号短);
换算(整数);
转换(无符号整数);
转换(长);
转换(无符号长);
转换(长-长);
转换(无符号长-长);
转换(浮动);
换算(双倍);
转换(长双);
T-var;
};
int main(int,char**)
{
N-n1;
n2;
int d=n1;
n1+n2;
返回0;
}
所以,基本上,正如你所看到的,我为它解释了一个基本的逻辑,在一系列条件中,类型之间的最小无损转换。但运行这个程序会得到:

test.cpp: In instantiation of ‘N<Return> N<T>::operator+(const N<Arg>&) const [with U = short int; Arg = int; Return = int; T = short int]’:
test.cpp:2542:8:   required from here
test.cpp:2507:17: error: ambiguous overload for ‘operator+’ (operand types are ‘const short int’ and ‘const N<int>’)
     { return var+i; };
                 ^
test.cpp:2507:17: note: candidate: operator+(int, int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, unsigned int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long unsigned int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long long int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long long unsigned int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, float) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, double) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long double) <built-in>
test.cpp:N::operator+(const N&)const[with U=short int;Arg=int;Return=int;T=short int]'的实例化:
测试。cpp:2542:8:从此处开始需要
test.cpp:2507:17:错误:“运算符+”的重载不明确(操作数类型为“const short int”和“const N”)
{返回var+i;};
^
测试cpp:2507:17:注:候选者:运算符+(int,int)
test.cpp:2507:17:注:候选者:运算符+(int,无符号int)
测试cpp:2507:17:注:候选者:运算符+(int,long int)
test.cpp:2507:17:注:候选者:运算符+(int,长无符号int)
测试cpp:2507:17:注:候选者:运算符+(int,long-long int)
test.cpp:2507:17:注:候选者:运算符+(int,long-unsigned int)
测试cpp:2507:17:注:候选:运算符+(int,float)
测试cpp:2507:17:注:候选者:运算符+(整数,双精度)
测试cpp:2507:17:注:候选者:运算符+(整数,长双精度)
…因为转换运算符都可以调用,所以编译器认为所有这些都是显式指定转换的同等有效选项。现在,如果我们切换到注释掉的转换宏,使每种类型只启用一个转换运算符,我们将得到:

test.cpp: In function ‘int main(int, char**)’:
test.cpp:2541:11: error: cannot convert ‘N<short int>’ to ‘int’ in initialization
   int d = n1;
           ^
test.cpp:在函数“int main(int,char**)”中:
test.cpp:2541:11:错误:无法在初始化时将“N”转换为“int”
int d=n1;
^
。。。因为编译器拒绝转换为short,然后将其转换为int,所以它需要显式的直接转换运算符

我清楚地知道,我可以通过在主函数中使用显式强制转换来实现这一点。但这不是重点,重点是透明包装,一个行为类似于基类型(不需要显式强制转换)的类


<> Pc>在C++中物理上是不可能的吗?(

我想我每个人都明白了!这不是最漂亮的代码,但似乎很管用。首先,我要指出的是,我将问题分解为两种变体:“StrongNumber”,它试图始终返回包装好的数字类;以及“WeakNumber”,它总是试图返回一个基类型。关键是-是什么让它难看-避免使用模板。模板只会导致编译器混乱

template <class T>
class StrongNumber
{
public:
  StrongNumber() {};
  StrongNumber(const T& _var) : var(_var) {};
  StrongNumber(const StrongNumber<T>& i) : var(i.var) {};

  #define DECLARE_HELPER(x, y) \
  auto operator x (const StrongNumber<long double>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };  \
  auto operator x (const StrongNumber<double>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };   \
  auto operator x (const StrongNumber<float>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };    \
  auto operator x (const StrongNumber<unsigned long long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };   \
  auto operator x (const StrongNumber<long long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };    \
  auto operator x (const StrongNumber<unsigned long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };\
  auto operator x (const StrongNumber<long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };     \
  auto operator x (const StrongNumber<unsigned int>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
  auto operator x (const StrongNumber<int>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };      \
  auto operator x (const StrongNumber<unsigned short>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };   \
  auto operator x (const StrongNumber<short>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };    \
  auto operator x (const StrongNumber<unsigned char>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };\
  auto operator x (const StrongNumber<char>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };     \
  auto operator x (const StrongNumber<bool>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };     \
  auto operator x (const long double i) y { return StrongNumber<decltype(var x i)>(var x i); };         \
  auto operator x (const double i) y { return StrongNumber<decltype(var x i)>(var x i); };              \
  auto operator x (const float i) y { return StrongNumber<decltype(var x i)>(var x i); };               \
  auto operator x (const unsigned long long i) y { return StrongNumber<decltype(var x i)>(var x i); };      \
  auto operator x (const long long i) y { return StrongNumber<decltype(var x i)>(var x i); };           \
  auto operator x (const unsigned long i) y { return StrongNumber<decltype(var x i)>(var x i); };           \
  auto operator x (const long i) y { return StrongNumber<decltype(var x i)>(var x i); };                \
  auto operator x (const unsigned int i) y { return StrongNumber<decltype(var x i)>(var x i); };            \
  auto operator x (const int i) y { return StrongNumber<decltype(var x i)>(var x i); };             \
  auto operator x (const unsigned short i) y { return StrongNumber<decltype(var x i)>(var x i); };          \
  auto operator x (const short i) y { return StrongNumber<decltype(var x i)>(var x i); };               \
  auto operator x (const unsigned char i) y { return StrongNumber<decltype(var x i)>(var x i); };           \
  auto operator x (const char i) y { return StrongNumber<decltype(var x i)>(var x i); };                \
  auto operator x (const bool i) y { return StrongNumber<decltype(var x i)>(var x i); };

  #define DECLARE(x)       DECLARE_HELPER(x, )
  #define DECLARE_CONST(x) DECLARE_HELPER(x, const)
  #define DECLARE_UNARY(x) auto operator x () { return StrongNumber<decltype(x var)>(x var); };
  #define DECLARE_UNARY_CONST(x) auto operator x () const { return StrongNumber<decltype(x var)>(x var); };

  operator T() const { return var; };

  DECLARE_CONST(%);
  DECLARE_CONST(+);
  DECLARE_CONST(-);
  DECLARE_CONST(*);
  DECLARE_CONST(/);
  DECLARE_CONST(&);
  DECLARE_CONST(|);
  DECLARE_CONST(^);
  DECLARE_CONST(<<);
  DECLARE_CONST(>>);
  DECLARE(=);
  DECLARE(+=);
  DECLARE(-=);
  DECLARE(*=);
  DECLARE(/=);
  DECLARE(&=);
  DECLARE(|=);
  DECLARE(^=);
  DECLARE(<<=);
  DECLARE(>>=);
  DECLARE_CONST(==);
  DECLARE_CONST(!=);
  DECLARE_CONST(>);
  DECLARE_CONST(<);
  DECLARE_CONST(>=);
  DECLARE_CONST(<=);
  DECLARE_UNARY(++);
  DECLARE_UNARY(--);
  DECLARE_UNARY_CONST(+);
  DECLARE_UNARY_CONST(-);
  DECLARE_UNARY_CONST(~);
  DECLARE_UNARY_CONST(!);
  explicit operator std::string() const { return std::to_string(var); };
  static int size() { return sizeof(T); };

  T var;
};

template <class T>
class WeakNumber
{
public:
  WeakNumber() {};
  WeakNumber(const T& _var) : var(_var) {};
  WeakNumber(const WeakNumber<T>& i) : var(i.var) {};

  #undef DECLARE_HELPER
  #define DECLARE_HELPER(x, y) \
  auto operator x (const WeakNumber<long double>& i) y { return var x i.var; }; \
  auto operator x (const WeakNumber<double>& i) y { return var x i.var; };      \
  auto operator x (const WeakNumber<float>& i) y { return var x i.var; };       \
  auto operator x (const WeakNumber<unsigned long long>& i) y { return var x i.var; };  \
  auto operator x (const WeakNumber<long long>& i) y { return var x i.var; };   \
  auto operator x (const WeakNumber<unsigned long>& i) y { return var x i.var; };   \
  auto operator x (const WeakNumber<long>& i) y { return var x i.var; };        \
  auto operator x (const WeakNumber<unsigned int>& i) y { return var x i.var; };    \
  auto operator x (const WeakNumber<int>& i) y { return var x i.var; };     \
  auto operator x (const WeakNumber<unsigned short>& i) y { return var x i.var; };  \
  auto operator x (const WeakNumber<short>& i) y { return var x i.var; };       \
  auto operator x (const WeakNumber<unsigned char>& i) y { return var x i.var; };   \
  auto operator x (const WeakNumber<char>& i) y { return var x i.var; };        \
  auto operator x (const WeakNumber<bool>& i) y { return var x i.var; };        \
  auto operator x (const long double i) y { return var x i; };          \
  auto operator x (const double i) y { return var x i; };           \
  auto operator x (const float i) y { return var x i; };            \
  auto operator x (const unsigned long long i) y { return var x i; };       \
  auto operator x (const long long i) y { return var x i; };            \
  auto operator x (const unsigned long i) y { return var x i; };        \
  auto operator x (const long i) y { return var x i; };             \
  auto operator x (const unsigned int i) y { return var x i; };         \
  auto operator x (const int i) y { return var x i; };              \
  auto operator x (const unsigned short i) y { return var x i; };       \
  auto operator x (const short i) y { return var x i; };            \
  auto operator x (const unsigned char i) y { return var x i; };        \
  auto operator x (const char i) y { return var x i; };             \
  auto operator x (const bool i) y { return var x i; };

  #undef DECLARE
  #undef DECLARE_CONST
  #undef DECLARE_UNARY
  #undef DECLARE_UNARY_CONST
  #define DECLARE(x)       DECLARE_HELPER(x, )
  #define DECLARE_CONST(x) DECLARE_HELPER(x, const)
  #define DECLARE_UNARY(x) auto operator x () { return x var; };
  #define DECLARE_UNARY_CONST(x) auto operator x () const { return x var; };

  operator T() const { return var; };

  DECLARE_CONST(%);
  DECLARE_CONST(+);
  DECLARE_CONST(-);
  DECLARE_CONST(*);
  DECLARE_CONST(/);
  DECLARE_CONST(&);
  DECLARE_CONST(|);
  DECLARE_CONST(^);
  DECLARE_CONST(<<);
  DECLARE_CONST(>>);
  DECLARE(=);
  DECLARE(+=);
  DECLARE(-=);
  DECLARE(*=);
  DECLARE(/=);
  DECLARE(&=);
  DECLARE(|=);
  DECLARE(^=);
  DECLARE(<<=);
  DECLARE(>>=);
  DECLARE_CONST(==);
  DECLARE_CONST(!=);
  DECLARE_CONST(>);
  DECLARE_CONST(<);
  DECLARE_CONST(>=);
  DECLARE_CONST(<=);
  DECLARE_UNARY(++);
  DECLARE_UNARY(--);
  DECLARE_UNARY_CONST(+);
  DECLARE_UNARY_CONST(-);
  DECLARE_UNARY_CONST(~);
  DECLARE_UNARY_CONST(!);
  // A couple more just because they're useful
  explicit operator std::string() const { return std::to_string(var); }; 
  static int size() { return sizeof(T); };

  T var;
};
模板
类strong编号
{
公众:
StrongNumber(){};
StrongNumber(const T&_var):var(_var){};
StrongNumber(conststrongnumber&i):var(i.var){};
#定义DECLARE_HELPER(x,y)\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const long double i)y{return StrongNumber(var x i);}\
自动运算符x(const double i)y{return StrongNumber(var x i);}\
自动运算符x(常量浮点i)y{return StrongNumber(var x i);}\
自动运算符x(const unsigned long long i)y{return StrongNumber(var x i);}\
自动运算符x(const long long i)y{return StrongNumber(var x i);}\
自动运算符x(const unsigned long i)y{return StrongNumber(var x i);}\
自动运算符x(const long i)y{return StrongNumber(var x i);}\
自动运算符x(const unsigned int i)y{return StrongNumber(var x i);}\
自动运算符x(const int i)y{返回强数(var x i);}\
自动运算符x(const unsigned short i)y{return StrongNumber(var x i);}\
自动运算符x(const short i)y{return StrongNumber(var x i);}\
自动运算符x(常量无符号字符i)y{return StrongNu
template <class T>
class StrongNumber
{
public:
  StrongNumber() {};
  StrongNumber(const T& _var) : var(_var) {};
  StrongNumber(const StrongNumber<T>& i) : var(i.var) {};

  #define DECLARE_HELPER(x, y) \
  auto operator x (const StrongNumber<long double>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };  \
  auto operator x (const StrongNumber<double>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };   \
  auto operator x (const StrongNumber<float>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };    \
  auto operator x (const StrongNumber<unsigned long long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };   \
  auto operator x (const StrongNumber<long long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };    \
  auto operator x (const StrongNumber<unsigned long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };\
  auto operator x (const StrongNumber<long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };     \
  auto operator x (const StrongNumber<unsigned int>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
  auto operator x (const StrongNumber<int>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };      \
  auto operator x (const StrongNumber<unsigned short>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };   \
  auto operator x (const StrongNumber<short>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };    \
  auto operator x (const StrongNumber<unsigned char>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };\
  auto operator x (const StrongNumber<char>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };     \
  auto operator x (const StrongNumber<bool>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };     \
  auto operator x (const long double i) y { return StrongNumber<decltype(var x i)>(var x i); };         \
  auto operator x (const double i) y { return StrongNumber<decltype(var x i)>(var x i); };              \
  auto operator x (const float i) y { return StrongNumber<decltype(var x i)>(var x i); };               \
  auto operator x (const unsigned long long i) y { return StrongNumber<decltype(var x i)>(var x i); };      \
  auto operator x (const long long i) y { return StrongNumber<decltype(var x i)>(var x i); };           \
  auto operator x (const unsigned long i) y { return StrongNumber<decltype(var x i)>(var x i); };           \
  auto operator x (const long i) y { return StrongNumber<decltype(var x i)>(var x i); };                \
  auto operator x (const unsigned int i) y { return StrongNumber<decltype(var x i)>(var x i); };            \
  auto operator x (const int i) y { return StrongNumber<decltype(var x i)>(var x i); };             \
  auto operator x (const unsigned short i) y { return StrongNumber<decltype(var x i)>(var x i); };          \
  auto operator x (const short i) y { return StrongNumber<decltype(var x i)>(var x i); };               \
  auto operator x (const unsigned char i) y { return StrongNumber<decltype(var x i)>(var x i); };           \
  auto operator x (const char i) y { return StrongNumber<decltype(var x i)>(var x i); };                \
  auto operator x (const bool i) y { return StrongNumber<decltype(var x i)>(var x i); };

  #define DECLARE(x)       DECLARE_HELPER(x, )
  #define DECLARE_CONST(x) DECLARE_HELPER(x, const)
  #define DECLARE_UNARY(x) auto operator x () { return StrongNumber<decltype(x var)>(x var); };
  #define DECLARE_UNARY_CONST(x) auto operator x () const { return StrongNumber<decltype(x var)>(x var); };

  operator T() const { return var; };

  DECLARE_CONST(%);
  DECLARE_CONST(+);
  DECLARE_CONST(-);
  DECLARE_CONST(*);
  DECLARE_CONST(/);
  DECLARE_CONST(&);
  DECLARE_CONST(|);
  DECLARE_CONST(^);
  DECLARE_CONST(<<);
  DECLARE_CONST(>>);
  DECLARE(=);
  DECLARE(+=);
  DECLARE(-=);
  DECLARE(*=);
  DECLARE(/=);
  DECLARE(&=);
  DECLARE(|=);
  DECLARE(^=);
  DECLARE(<<=);
  DECLARE(>>=);
  DECLARE_CONST(==);
  DECLARE_CONST(!=);
  DECLARE_CONST(>);
  DECLARE_CONST(<);
  DECLARE_CONST(>=);
  DECLARE_CONST(<=);
  DECLARE_UNARY(++);
  DECLARE_UNARY(--);
  DECLARE_UNARY_CONST(+);
  DECLARE_UNARY_CONST(-);
  DECLARE_UNARY_CONST(~);
  DECLARE_UNARY_CONST(!);
  explicit operator std::string() const { return std::to_string(var); };
  static int size() { return sizeof(T); };

  T var;
};

template <class T>
class WeakNumber
{
public:
  WeakNumber() {};
  WeakNumber(const T& _var) : var(_var) {};
  WeakNumber(const WeakNumber<T>& i) : var(i.var) {};

  #undef DECLARE_HELPER
  #define DECLARE_HELPER(x, y) \
  auto operator x (const WeakNumber<long double>& i) y { return var x i.var; }; \
  auto operator x (const WeakNumber<double>& i) y { return var x i.var; };      \
  auto operator x (const WeakNumber<float>& i) y { return var x i.var; };       \
  auto operator x (const WeakNumber<unsigned long long>& i) y { return var x i.var; };  \
  auto operator x (const WeakNumber<long long>& i) y { return var x i.var; };   \
  auto operator x (const WeakNumber<unsigned long>& i) y { return var x i.var; };   \
  auto operator x (const WeakNumber<long>& i) y { return var x i.var; };        \
  auto operator x (const WeakNumber<unsigned int>& i) y { return var x i.var; };    \
  auto operator x (const WeakNumber<int>& i) y { return var x i.var; };     \
  auto operator x (const WeakNumber<unsigned short>& i) y { return var x i.var; };  \
  auto operator x (const WeakNumber<short>& i) y { return var x i.var; };       \
  auto operator x (const WeakNumber<unsigned char>& i) y { return var x i.var; };   \
  auto operator x (const WeakNumber<char>& i) y { return var x i.var; };        \
  auto operator x (const WeakNumber<bool>& i) y { return var x i.var; };        \
  auto operator x (const long double i) y { return var x i; };          \
  auto operator x (const double i) y { return var x i; };           \
  auto operator x (const float i) y { return var x i; };            \
  auto operator x (const unsigned long long i) y { return var x i; };       \
  auto operator x (const long long i) y { return var x i; };            \
  auto operator x (const unsigned long i) y { return var x i; };        \
  auto operator x (const long i) y { return var x i; };             \
  auto operator x (const unsigned int i) y { return var x i; };         \
  auto operator x (const int i) y { return var x i; };              \
  auto operator x (const unsigned short i) y { return var x i; };       \
  auto operator x (const short i) y { return var x i; };            \
  auto operator x (const unsigned char i) y { return var x i; };        \
  auto operator x (const char i) y { return var x i; };             \
  auto operator x (const bool i) y { return var x i; };

  #undef DECLARE
  #undef DECLARE_CONST
  #undef DECLARE_UNARY
  #undef DECLARE_UNARY_CONST
  #define DECLARE(x)       DECLARE_HELPER(x, )
  #define DECLARE_CONST(x) DECLARE_HELPER(x, const)
  #define DECLARE_UNARY(x) auto operator x () { return x var; };
  #define DECLARE_UNARY_CONST(x) auto operator x () const { return x var; };

  operator T() const { return var; };

  DECLARE_CONST(%);
  DECLARE_CONST(+);
  DECLARE_CONST(-);
  DECLARE_CONST(*);
  DECLARE_CONST(/);
  DECLARE_CONST(&);
  DECLARE_CONST(|);
  DECLARE_CONST(^);
  DECLARE_CONST(<<);
  DECLARE_CONST(>>);
  DECLARE(=);
  DECLARE(+=);
  DECLARE(-=);
  DECLARE(*=);
  DECLARE(/=);
  DECLARE(&=);
  DECLARE(|=);
  DECLARE(^=);
  DECLARE(<<=);
  DECLARE(>>=);
  DECLARE_CONST(==);
  DECLARE_CONST(!=);
  DECLARE_CONST(>);
  DECLARE_CONST(<);
  DECLARE_CONST(>=);
  DECLARE_CONST(<=);
  DECLARE_UNARY(++);
  DECLARE_UNARY(--);
  DECLARE_UNARY_CONST(+);
  DECLARE_UNARY_CONST(-);
  DECLARE_UNARY_CONST(~);
  DECLARE_UNARY_CONST(!);
  // A couple more just because they're useful
  explicit operator std::string() const { return std::to_string(var); }; 
  static int size() { return sizeof(T); };

  T var;
};
template<class T1, class T2, class T3>
T3 foo()
{
  StrongNumber<T1> n1;
  StrongNumber<T2> n2;
  T3 d = n1;
  n1 + n2;
  n1 + 1;
  n1 + 1.0;
  d = d + n1;
  d += 1 + n1;
  d += 1.0 + n1;
  return d;
}
std::cout << foo<short, long long, int>() << std::endl;