你可以使用SFINAE只讓兩個重載之一,參與過載的分辨率,基於該類型T
是否是一樣的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;
}
兩個std::enable_if
和std::is_same
可以輕鬆實現如果你不能使用標準庫中的那些。例如:
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; };
這裏是一個live example。
對於靜態斷言的問題,可以定義一個簡單的特徵來檢查給定的類型是否存在於給定的元組類型中(這個特徵也可以根據std::conditional
定義,這也是微不足道的) :
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;
};
,然後用它像這樣:
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>();
}
下面是一個使用上述static_assert()
一個live example。
如果你也想測試一個元組是否包含某種類型只有一次,你可以使用下面的特質,這是has_type
特質上面的一個微不足道的修改:
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;
};
並使用它像這樣:
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>();
}
這是live example。