生成包含给定类型的N个参数的可变参数列表的最佳方法?

问题描述 投票:3回答:2

有一个形式的类模板:

template <typename ...T> Bag {};

具有许多有用的功能,但某些实现留给派生类。通常,这会通过重复一次N次来实例化。而不是像这样定义类:

class BoolBag3 : public Bag<bool, bool, bool> {};
class IntBag2 : public Bag<int, int> {};

我有兴趣参加类似的课程:

template<size_t N, typename T> class UniBag : public Bag< ... > {}

尤其是,当所有类型相同时,可以以通用方式实现Bag中的某些纯虚拟机。什么是最简单/最优雅的方法?

到目前为止,我已经做过:使用this答案中的模式生成TypeSequence

template<class T> using InvokeType = typename T::type;  // InvokeType is an alias for T::type.
template<class S1, class S2> struct concat;

// Type sequence.

template<typename ... T> struct TypeSequence{ using type = TypeSequence; };

template<typename ... T, typename ... U> 
struct concat<TypeSequence<T ...>, TypeSequence<U ...>> : TypeSequence<T ..., U ...>{};
template<class S1, class S2> using Concat = InvokeType<concat<S1, S2>>;

template<typename T, size_t N> struct gen_type_seq;
template<typename T, size_t N> using GenTypeSeq = InvokeType<gen_type_seq<T, N>>;

template<typename T, size_t N> 
struct gen_type_seq : Concat<GenTypeSeq<T, N/2>, GenTypeSeq<T, N - N/2>>{};

template<typename T> struct gen_type_seq<T, 0> : TypeSequence<>{};
template<typename T> struct gen_type_seq<T, 1> : TypeSequence<T>{};

然后使用中间类将TypeSequence转换为可变参数列表:

template <typename T> class UniBagHelper {};
template <typename ... T> class UniBagHelper<TypeSequence<T ...>> : public Bag<T ...> {};

template <typename T, size_t N> class UniBag : public UniBagHelper<GenTypeSeq<T, N>> {};

UniBag<bool, 4> logicBag;
c++ templates variadic-templates
2个回答
1
投票

沿着这些思路的东西,也许:

template <typename T, size_t dummy>
using EatIndex = T;

template <typename T, std::size_t... I>
Bag<EatIndex<T, I>...> MakeBagN(std::index_sequence<I...>);

template<size_t N, typename T>
using BagN = decltype(MakeBagN<T>(std::make_index_sequence<N>()));

template<size_t N, typename T>
class UniBag : public BagN<N, T> {};

Demo


2
投票

C ++ 14引入了std::index_sequence,因此您可能直接拥有:

std::index_sequence

然后

template <typename T, std::size_t> using always_t = T;

template <typename T> struct BagTNHelper;

template <typename T, std::size_t ... Is>
struct BagTNHelper<T, std::index_sequence<Is ...>>
{
    using type = Bag<always_t<T, Is>...>;
};

template <typename T, size_t N>
using BagTN = typename BagTNHelper<T, std::make_index_sequence<N>>::type;
© www.soinside.com 2019 - 2024. All rights reserved.