这个特征类适用于任何类型的包,无论是它type_set
还是std::tuple
:
#include <type_traits>
template<typename T, typename L> struct is_contained; // illegal
template<typename T, template<typename...>class L>
struct is_contained< T, L<> > : std::false_type {};
template<typename T, template<typename...>class L, typename T0, typename... Ts>
struct is_contained< T, L<T0, Ts...> > :
std::integral_constant< bool,
std::is_same<T, T0>::value
|| is_contained< T, L<Ts...> >::value
>
{};
但是,我发现index_of
更有用:
template<typename T, typename L, typename=void> struct index_of; // illegal
template<typename T, template<typename...>class L>
struct index_of< T, L<>, void > {}; // SFINAE enable
template<typename T, template<typename...>class L, typename T0, typename... Ts>
struct index_of<
T,
L<T0, Ts...>,
typename std::enable_if<!std::is_same<T, T0>>::type
> : std::integral_constant< std::size_t, 1 + index_of< T, L<Ts...> >::value >
{};
template<typename T, template<typename...>class L, typename T0, typename... Ts>
struct index_of<
T,
L<T0, Ts...>,
typename std::enable_if<std::is_same<T, T0>>::type
> : std::integral_constant< std::size_t, 0 >
{};
它还允许您通过 SFINAE 检查是否存在,因为index_of<T,List>::value
存在 iffT
位于List
.
接下来,我将在构造函数上启用完美转发:
template<typename T>
using RemoveRefCv = typename std::remove_cv< typename remove_ref< T >::type >::type;
struct C
{
using constructible_from_types = std::tuple< int, double, short >;
template< typename T, std::size_t=std::index_of<RemoveRefCv<T0>>::value >
C(T&&);
};
(假设您不想担心可以从列表中构建const
但不是非const
列表)。
您可以更进一步,接受任何T
可转换为列表中任何类型的内容。这可能需要一些智能来确定您如何处理冲突。一个简单的方法可能是找到一个完美的匹配,然后找到第一个可以转换的匹配。
如果你看一下index_of
,你会注意到它的大部分工作都是通过查询来完成的std::is_same
。您可以编写search_for
将二进制bool
ean 模板作为参数的 a,并在列表中查找第一个匹配的模板。
template<template<typename, typename>class Func, typename T, typename L, typename=void> struct search_for; // illegal
template<template<typename, typename>class Func, typename T, template<typename...>class L>
struct search_for< Func, T, L<>, void > {}; // SFINAE enable
template<
template<typename, typename>class Func,
typename T,
template<typename...>class L,
typename T0,
typename... Ts
>
struct search_for<
Func,
T,
L<T0, Ts...>,
typename std::enable_if<!Func< T, T0 >::value
> : std::integral_constant<
std::size_t,
1 + search_for< Func, T, L<Ts...> >::value
> {};
template<
template<typename, typename>class Func,
typename T,
template<typename...>class L,
typename T0,
typename... Ts
>
struct search_for<
Func,
T,
L<T0, Ts...>,
typename std::enable_if<Func<T, T0>::value>::type
> : std::integral_constant< std::size_t, 0 >
{};
template<template<typename,typename>class Func, typename T, typename L>
using SearchFor = search_for<Func, T, L>;
然后我会index_of
根据以下内容重写:
template<typename T, typename List>
struct index_of:SearchFor<std::is_same, T, List> {};
然后编写一个尝试的类,index_of
如果尝试失败search_for< std::is_constructable, ... >
,则提取该索引,然后使用该类型将传入的参数转换为列表中的索引类型:
template<std::size_t n, typename L>
struct get_type {};// SFINAE enabled
template<std::size_t n, template<typename...>class L>
struct get_type< n, L<> > {};
template<template<typename...>class L, typename T0, typename... Ts>
struct get_type< 0, L<T0, Ts...> > {
typedef T0 type;
};
template<std::size_t n, template<typename...>class L, typename T0, typename... Ts>
struct get_type< n, L<T0, Ts...> >:
get_type< n-1, L<Ts...> >
{};
template<std::size_t n, typename List>
using GetType = typename get_type<n, List>::type;
因为如果您不这样做,并且您的类型是由 an 构造的,int
并且有人传入 ashort
或 anunsigned int
或其他任何内容,那么您的 SFINAE 代码将拒绝从您的类型列表中不完美的东西构造。