#include <cstdint>
 
#include <iostream>
#include <limits>
 
#define define_result_type( t1, t2, r )\
template <>\
struct addition_result<t1,t2> {\
    typedef r type;\
}
 
template <typename T1, typename T2>
struct addition_result;
 
define_result_type(int8_t, int8_t, int16_t);
define_result_type(int16_t, int16_t, int32_t);
define_result_type(int32_t, int32_t, int64_t);
 
template<typename T1, typename T2>
typename addition_result<T1,T2>::type
add( T1 const & lhs, T2 const & rhs ) {
    typedef typename addition_result<T1,T2>::type result_type;

    return result_type(lhs) + result_type(rhs);
};
 
int main() {
   using namespace std;
   
   int32_t a, b;
   a = b = numeric_limits<decltype(a)>::max();

   cout << a + b << endl;
   cout << add(a, b) << endl;
}