您可以使用 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; };
这是一个活生生的例子。
对于静态断言,您可以定义一个简单的 trait 来检查给定类型是否存在于给定的元组类型中(这个 trait 也可以用 来定义,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()
。
如果您还想测试一个元组是否只包含某个类型一次,您可以使用以下特征,这是对上述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>();
}
这是一个活生生的例子。