#include <iostream>
#include <typeinfo>
#include <cstddef>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
typedef void *E;
template<int n> struct Idx { E v[n]; };
Idx<1> sel(...);
Idx<2> sel(long);
Idx<3> sel(unsigned long);
Idx<4> sel(double);
template<std::size_t n>
struct ResultSub2 { typedef void type; };
template<> struct ResultSub2<2> { typedef long type; };
template<> struct ResultSub2<3> { typedef unsigned long type; };
template<> struct ResultSub2<4> { typedef double type; };
template<typename T> T &rett();
template<typename T>
struct ResultSub: ResultSub2<sizeof(sel(rett<T>())) / sizeof(E)> {};
template<typename T>
struct Result:
boost::mpl::eval_if_c<
std::numeric_limits<T>::is_integer,
boost::mpl::if_c<
std::numeric_limits<T>::is_signed,
long,
unsigned long>,
ResultSub<T> >
{};
template<typename T>
void print(const T &)
{
typedef typename Result<T>::type U;
std::cout << typeid(T).name() << " -> " << typeid(U).name() << std::endl;
}
struct X { operator int() const; };
struct Y { operator float() const; };
struct Z {};
int main()
{
print(1);
print(1u);
print(1.0);
print(short(1));
print('x');
print(X()); // sel()の呼び出しで曖昧エラー
print(Y());
print(Z());
}