SFINAE类型集包含该类型 [英] SFINAE set of types contains the type

查看:64
本文介绍了SFINAE类型集包含该类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从类型 ... T 中的每种类型构造我的类 C类. sizeof ...(T)足够大,以至于我不想写出如下所示的所有构造函数变体:

I want to construct my class class C from each type in set of types ...T. sizeof...(T) is large enough so that I did not want to write out all the constructor variants as below:

// T : {T1, T2, ..., TN}
struct C
{
    C(T1);
    C(T2);
    ...
    C(TN); // Phew! I'm tired.
};

所以我想尝试下一个:

// type_set is something like template< typename... T > struct type_set {...};
struct C 
{
    using constructible_from_types = type_set< int, double, short >;
    template< typename T0 >
    C(T0, typename std::enable_if< is_contained< T0, constructible_from_types >::value >::type * = nullptr);
};
// or
// type_set is something like template< typename... T > struct type_set { template< typename T0 > constexpr bool is_contained() {...} ...}
struct C 
{
    using constructible_from_types = type_set< int, double, short >;
    template< typename T0 >
    C(T0, typename std::enable_if< constructible_from_types::is_contained< T0 >() >::type * = nullptr);
};

但是我不知道如何实现 is_contained 类型特征和 type_set 类.

But I don't know how to implement the is_contained type trait and type_set class.

并且,通常,人们对规范解决此问题感兴趣.

And, in general, interested in the canonical implementation of solution of this problem.

推荐答案

首先,一个更好的构造函数:

First off, a better constructor:

template <typename T,
          typename = typename std::enable_if<is_contained<T, T0, T1, T2>::value>
C(T) { }

// or C(T const &), or even C(T &&)
// and use "typename std::decay<T>::type" instead of just "T"

现在是特征:

#include <type_traits>

template <typename T, typename ...> struct is_contained : std::false_type { };

template <typename T, typename Head, typename ...Tail>
struct is_contained<T, Head, Tail...> : std::integral_constant<bool,
    std::is_same<T, Head>::value || is_contained<T, Tail...>::value> { };

要重复,用法是:

is_contained<T, double, int, char>::value

如果您希望将类型列表包装为另一种类型,这是一个简单的修改,但是我只使用 std :: tuple 作为包装类型.

If you prefer wrapping the type list into another type, that's a simple modification, but I'd just use std::tuple as the wrapper type.

在注释之后,这是一个带有通用引用的构造函数:

Following the comments, here's a constructor that takes a universal reference:

template <typename T,
          typename = std::enable_if<
              is_contained<typename std::decay<T>::type,
                           T0, T1, T2, T3>::value
                                   >::type>
C(T && t)
{  }

有了更多的魔术,您甚至可以遍历列表中的每个元素,查看构造函数参数是否可以可转换到列表项,但这可能与您想要的有所不同.

With even more magic you could even go through every element in your list and see if the constructor argument is convertible to the list item, but that may be different from what you want.

这篇关于SFINAE类型集包含该类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆