#include <type_traits>

using namespace std;

struct A
{
public:

	A(){}

    static A& singleton() 
	{
		static A obj;

		return obj;
	}


private:
	A(const A&);
	A& operator=(A const&);
};

struct A_1
{
    static A& singleton() 
	{
		static A obj;

		return obj;
	}
};

struct B
{
	B& singleton()
	{
		return *this;
	}
};

struct C
{
	int singleton;
};

void global_func(){}



template<class T>
struct is_function_pointer 
{
private:
	template<class T> 
	struct is_function_pointer_impl
	{
		typedef typename std::remove_pointer<T>::type pointee;
		typedef typename std::is_function<pointee>::type type;
	};

	typedef typename std::conditional
		<std::is_pointer<T>::value, is_function_pointer_impl<T>, std::false_type>
		::type cond_result_t;

public:
	static const bool value = cond_result_t::type::value;
};

template<typename T>
struct has_singleton_accessor
{
private:
	typedef decltype(&T::singleton) func_t;

public:
	static const bool value = is_function_pointer<func_t>::value
						&& !std::is_member_function_pointer<func_t>::value;
};

template<typename T>
struct satisfy_singleton_requirement
{
	enum {
		value = !std::is_trivially_copy_constructible<T>::value
			&&  !std::is_trivially_copy_assignable<T>::value
	};
};


template<typename T>
struct is_singleton
{
	static const bool value = has_singleton_accessor<T>::value
						&&  satisfy_singleton_requirement<T>::value;
};

int main()
{
	static_assert(is_function_pointer<decltype(&A::singleton)>::value, "true.");
	static_assert(is_function_pointer<decltype(&global_func)>::value, "also true.");

	static_assert(is_member_function_pointer<decltype(&B::singleton)>::value
		, "true.");

	static_assert(is_member_function_pointer<decltype(&A::singleton)>::value
		, "but it's false because A::singleton is the static member");

	//therefore:
	static_assert(is_function_pointer<decltype(&A::singleton)>::value
				&& !std::is_member_function_pointer<decltype(&A::singleton)>::value
		, "this is how to check whether A::singleton is static member function.");


	static_assert(is_singleton<A_1>::value, "this type isn't singleton.");	//Err
	static_assert(is_singleton<B>::value, "this type isn't singleton.");	//Err
	static_assert(is_singleton<C>::value, "this type isn't singleton.");	//Err

	static_assert(is_singleton<A>::value, "that's it!");
}