#include <iostream>
#include <iomanip>
#include <type_traits>
#include <sstream>

template<typename T>
struct has_size_method
{
private:
        typedef std::true_type yes;
        typedef std::false_type no;

        template<typename C>
        static yes test(int (C::*f)() const){
                return yes{};
        }

        template<typename C>
        static yes test(size_t (C::*f)() const){
                return yes{};
        }

        template<typename C>
        static auto test(decltype(&C::size),void*) -> decltype(test(&C::size)){
                return test(&C::size);
        }

        template<typename C>
        static no test(...){
                return no{};
        }

public:

        static constexpr bool value = std::is_same<decltype(test<T>(0,0)),yes>::value;
};

struct int_size{
	int size() const { return 42; };
};

struct derived_int_size : int_size{};

struct size_t_size{
	std::size_t size() const { return 42; }
};

struct derived_size_t_size : size_t_size{};

struct void_size{
	void size() {}
};

struct no_size{};

struct template_int_size{
	template<typename=int>
	int size() const { return 42; }
};

struct overloaded_size{
	size_t size() const { return 42; }
	int size() { return 41; }
};

int main()
{
	using namespace std;
#define dbg(x) { stringstream s; s << boolalpha << left << setw(8) << has_size_method<x>::value << #x; cout << s.str() << endl; }

	dbg(int_size);
	dbg(derived_int_size);
	dbg(size_t_size);
	dbg(derived_size_t_size);
	dbg(void_size);
	dbg(no_size);
	dbg(template_int_size);
	dbg(overloaded_size);
}