You can use SFINAE to participate in an overload of only one of two overloads, based on whether the type T is the same as Head :
#include <type_traits> // For std::enable_if and std::is_same template<typename T, typename std::enable_if<!std::is_same<T, Head>::value>::type* = nullptr> T& get() { return rest.get<T>(); } template<typename T, typename std::enable_if<std::is_same<T, Head>::value>::type* = nullptr> Head& get() { return data; }
Both std::enable_if and std::is_same can be easily implemented if you cannot use them from the standard library. For instance:
template<typename T, typename U> struct is_same { static constexpr bool value = false; }; template<typename T> struct is_same<T, T> { static constexpr bool value = true; }; template<bool C, typename T = void> struct enable_if { }; template<typename T> struct enable_if<true, T> { using type = T; };
Here is a living example .
As for the static statement, you can define a simple attribute that checks for the presence of a given type in a given type (this attribute can also be defined in terms of std::conditional , which is also trivial to implement):
template<typename...> struct SimpleTuple; template<typename T, typename U> struct has_type { static constexpr bool value = false; }; template<typename T, typename U, typename... Ts> struct has_type<T, SimpleTuple<U, Ts...>> { static constexpr bool value = has_type<T, SimpleTuple<Ts...>>::value; }; template<typename T, typename... Ts> struct has_type<T, SimpleTuple<T, Ts...>> { static constexpr bool value = true; }; template<typename T> struct has_type<T, SimpleTuple<>> { static constexpr bool value = false; };
And then use it like this:
template<typename T, typename enable_if<!is_same<T, Head>::value>::type* = nullptr> T& get() { static_assert(has_type<T, SimpleTuple>::value, "Type not found!"); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ return rest.get<T>(); }
Here is a live example that uses static_assert() above.
If you also want to check whether a tuple contains a certain type only once, you can use the following attribute, which is a trivial modification of the has_type attribute above:
template<typename...> struct SimpleTuple; template<typename T, typename U> struct has_unique_type { static constexpr bool value = false; }; template<typename T, typename U, typename... Ts> struct has_unique_type<T, SimpleTuple<U, Ts...>> { static constexpr bool value = has_unique_type<T, SimpleTuple<Ts...>>::value; }; template<typename T, typename... Ts> struct has_unique_type<T, SimpleTuple<T, Ts...>> { static constexpr bool value = !has_unique_type<T, SimpleTuple<Ts...>>::value; }; template<typename T> struct has_unique_type<T, SimpleTuple<>> { static constexpr bool value = false; };
And use it like this:
template<typename T, typename enable_if<!is_same<T, Head>::value>::type* = nullptr> T& get() { static_assert(has_unique_type<T, SimpleTuple>::value, "Type not found or not unique!"); return rest.get<T>(); }
Here is a living example .