#include <iostream>
#include <type_traits>

template<typename TypeHead, typename... TypeTail>
struct TypesList
{
	typedef TypeHead head;
	typedef TypesList<TypeTail...> tail;

	enum { Length = 1 + tail::Length };
	static const bool isLast = false;

	template<typename QueryType>
	struct Contains
	{
		static const bool value = std::is_same<QueryType, TypeHead>::value || 
			tail::template Contains<QueryType>::value;
	};
};

template<typename TypeHead>
struct TypesList<TypeHead>
{
	typedef TypeHead head;

	enum { Length = 1 };
	static const bool isLast = true;

	template<typename QueryType>
	struct Contains
	{
		static const bool value = std::is_same<QueryType, TypeHead>::value;
	};
};

template<typename T>
void foo(const T &arg) {
	typedef TypesList<int, float, char> AllowedTypes;

	static_assert(AllowedTypes::Contains<T>::value, "Not allowed type: ");

	// do some stuff here
}

struct Yoba {};

int main()
{
	auto num = 5;
	foo(num);

	Yoba yoba;
	foo(yoba);

	return 0;
}
