c++ 使用包模板类型创建

jmp7cifd  于 2023-07-01  发布在  其他
关注(0)|答案(2)|浏览(136)

我有一个类,它被传递了任意数量的模板参数。我想创建一个using来存储它们
我想了很久,没有找到合适的答案

template <typename... Ts>
class TypeSet {
  using T = Ts; // something like that
}

template<typename... Ts>
constexpr auto return_unique() {
   // something to create TypeSet<NewTs...> set
   return set;
}

// return_unique<int, int> -->  TypeSet<int>

template <typename... Ts>
class myobj {
   using unique_template = return_unique<Ts...>()::T;
}
pes8fvy9

pes8fvy91#

给定一个X = TypeSet<T...>,你可以像这样得到一个参数包T...

[]<typename... T>(TypeSet<T...>) { /* Use T... in here*/ }(X{})

您也可以将它们存储在std::tuple中:using T = std::tuple<Ts...>;。或者,同样,您可以使用TypeSet本身来保存类型:using T = TypeSet<Ts...>

gpfsuwkq

gpfsuwkq2#

我有一个类,它被传递了任意数量的模板参数。我想创建一个using来存储它们
我有一个模板函数,它将返回一个具有模板值的TypeSet对象 没有重复。我想得到这些模板参数的包
例如return_unique<int, int, float>--> TypeSet<int, float>
让我们使用您已经拥有的TypeSet,进行一次调整:我们不需要using T部分。
这应该做到:

template <class... Ts>
struct TypeSet{};

现在我们需要一种方法来检查在给定的TypeSet中是否存在 any 类型T。现在我将介绍一个检查Any-稍后我们将看到如何用一行程序来替换它。
让我们从 false case开始:

#include <type_traits>

template <class T, class ... Ts>
struct Any : std::false_type {};

这将是以下情况“失败”时的回退情况:
真实案例(True Case):在TypeSet的头部有一个T

template <class T, class ... Ts>
struct Any<T, TypeSet<T, Ts...>> : std::true_type {};

最后:在TypeSet的头部没有T?检查一下尾部

template <class T, class U, class ... Ts>
struct Any<T, TypeSet<U, Ts...>> : Any<T, TypeSet<Ts...>> {};

有了这个,我们就可以实现您的 * 独特 *。实现它的一种方法是从给定的列表中逐个取出元素T到内部列表(我们称之为L),如果!Any<T, L>::value
让我们从基本案例开始:

template <class /* To */, class ... /* From */>
struct Unique_impl;

template <class ... Ts>
struct Unique_impl<TypeSet<Ts...>, TypeSet<>>
{ using type = TypeSet<Ts...>; };

也就是说,如果我们已经用尽了From列表,我们就剩下To列表了。
最后

template <class T, class ... Ts, class ... Us>
struct Unique_impl<TypeSet<Us...>, TypeSet<T, Ts...>> :
    std::conditional_t
        < Any<T, TypeSet<Us...>>::value                  // T in internal list?
        , Unique_impl<TypeSet<Us...>, TypeSet<Ts...>>    // Yes: We skip it
        , Unique_impl<TypeSet<Us..., T>, TypeSet<Ts...>> // No:  We add it
        >
{};

还有一个化名让一切更方便(注意,我们给予它一个空的TypeSet<>作为我们的内部列表开始)

template <class T>
using Unique = typename Unique_impl<TypeSet<>, T>::type;

现在我们只需要确认它是否有效:

static_assert(std::is_same_v<Unique<TypeSet<int,int,float>>, TypeSet<int,float>>);

编辑:感谢Jarod42的精彩评论
Any<T, TypeSet<Us...>>::value可以替换为(std::is_same_v<T, Us> || ...)
节省了代码行-我们最终得到了

template <class T, class ... Ts, class ... Us>
struct Unique_impl<TypeSet<Us...>, TypeSet<T, Ts...>> :
    std::conditional_t
        < (std::is_same_v<T, Us> || ...)                 // T in internal list?
        , Unique_impl<TypeSet<Us...>, TypeSet<Ts...>>    // Yes: We skip it
        , Unique_impl<TypeSet<Us..., T>, TypeSet<Ts...>> // No:  We add it
        >
{};

相关问题