#include <iostream>

typedef std::size_t SizeType;

template<typename T>
struct Identity
{
	typedef T Type;
};

typedef Identity<char(&)[1]>::Type NoType;
typedef Identity<char(&)[2]>::Type YesType;

template<typename T, T Val>
struct IntegralConstant : public Identity<IntegralConstant<T, Val> >
{
	typedef T ValueType;

#ifdef Lib_Cpp11
	static constexpr ValueType Value = Val;
	constexpr operator ValueType() const
	{
		return this->Value;
	}
#else // Lib_Cpp11
	static const ValueType Value = Val;
	operator ValueType() const
	{
		return this->Value;
	}
#endif // Lib_Cpp11
};

template<SizeType Val>
struct SizeToType : public IntegralConstant<SizeType, Val>
{
};

template<bool Val>
struct BoolToType : public IntegralConstant<bool, Val>
{
};

template<typename T>
T& DeclVal();

namespace Detail
{
	template<typename From, typename To>
	class IsExplicitConvertible
	{
		template<typename FromT, typename ToT>
		static NoType Check(...);
		template<typename FromT, typename ToT>
		static YesType Check(SizeToType<sizeof(static_cast<ToT>(DeclVal<FromT>()))>*);

	public:
		static const bool Value = sizeof(Check<From, To>(0)) == sizeof(YesType);
	};

	template<typename T> 
	class IsDefaultConstructible 
	{ 
		template<typename U> 
		static NoType Check(...); 
		template<typename U> 
		static YesType Check(SizeToType<sizeof(U())>*); 

	public: 
		static const bool Value = sizeof(Check<T>(0)) == sizeof(YesType); 
	};
}

template<typename From, typename To>
struct IsExplicitConvertible : public BoolToType<Detail::IsExplicitConvertible<From, To>::Value>
{
};

template<typename T>
struct IsDefaultConstructible : public BoolToType<Detail::IsDefaultConstructible<T>::Value>
{
};

struct Foo1
{
	explicit Foo1(int);
	
	operator char();
};

class Foo2
{
	Foo2();
};

struct Foo3
{
};

int main()
{
	std::cout << IsExplicitConvertible<int, float>::Value << '\n';		// Sollte 1 sein
	std::cout << IsExplicitConvertible<int, Foo1>::Value << '\n';		// Sollte 1 sein
	std::cout << IsExplicitConvertible<float, Foo1>::Value << '\n';		// Sollte 1 sein
	std::cout << IsExplicitConvertible<Foo1, char>::Value << '\n';		// Sollte 1 sein
	std::cout << IsExplicitConvertible<Foo1, double>::Value << '\n';	// Sollte 1 sein
	std::cout << IsExplicitConvertible<bool, Foo2>::Value << '\n';		// Sollte 0 sein
	std::cout << IsExplicitConvertible<int, void*>::Value << '\n';		// Sollte 0 sein
	std::cout << '\n';
	std::cout << IsDefaultConstructible<int>::Value << '\n';			// Sollte 1 sein
	std::cout << IsDefaultConstructible<Foo1>::Value << '\n';			// Sollte 0 sein
	std::cout << IsDefaultConstructible<Foo2>::Value << '\n';			// Sollte 0 sein
	std::cout << IsDefaultConstructible<Foo3>::Value << '\n';			// Sollte 1 sein
}