c++ - 将类型插入/删除可变参数模板列表(参数包)

标签 c++ templates metaprogramming variadic-templates c++14

在可变参数模板类型列表(参数包)中实现基于索引的类型插入和删除的最佳方法是什么?

所需的代码/行为:

template<typename...> struct List { /* ... */ };

static_assert(is_same
<
    List<int, char, float>::Insert<int, 0>,
    List<int, int, char, float>
>());

static_assert(is_same
<
    List<int, char, float>::Insert<int, 2>,
    List<int, char, int, float>
>());

static_assert(is_same
<
    List<int, char, float>::Remove<0>,
    List<char, float>
>());

static_assert(is_same
<
    List<int, char, float>::Remove<1>,
    List<int, float>
>());

我尝试了一种基于推回最初为空列表中的参数的实现,但它很难阅读/维护。参数类似于:

template<typename T, int I, int ITarget, typename TResult> struct InsertImpl;

我不断递增 I直到等于 ITarget , 推回 TResult 中的现有类型,这是一个 List<...> .当I等于 ITarget ,我推回去TTResult

删除一个类型有一个类似的实现——当索引相等时我没有推回两次,我只是跳过了这个类型。

我的繁琐解决方案将根据推送和弹出来实现插入和删除。我相信推到前面等于 Insert<0> 会更优雅推到后面等于Insert<size> .这同样适用于从前面和后面弹出。

有更好的方法吗? C++14 特性有帮助吗?

最佳答案

不确定是否存在任何“最佳”方式,但这是一种非递归方式:

#include <utility>
#include <type_traits>
#include <tuple>

template<typename...Ts> struct List;

template<typename T> struct ListFromTupleImpl;
template<typename...Ts>
struct ListFromTupleImpl<std::tuple<Ts...>>
{ using type = List<Ts...>; };

template<typename T>
using ListFromTuple = typename ListFromTupleImpl<T>::type;

template<typename...Ts>
using TupleCat = decltype(std::tuple_cat(std::declval<Ts>()...));

template<typename...Ts>
using ListFromTupleCat = ListFromTuple<TupleCat<Ts...>>;

template<unsigned P,typename T,typename I> struct RemoveFromListImpl;
template<unsigned P,typename...Ts,std::size_t...Is>
struct RemoveFromListImpl<P,List<Ts...>,std::index_sequence<Is...>>
{
    using type = ListFromTupleCat<
       std::conditional_t<(Is==P),std::tuple<>,std::tuple<Ts>>...>;
};

// All elements < P
template<unsigned P,typename T,typename I> struct HeadImpl;
template<unsigned P,typename...Ts,std::size_t...Is>
struct HeadImpl<P,List<Ts...>,std::index_sequence<Is...>>
{
    using type = TupleCat<
       std::conditional_t<(Is>=P),std::tuple<>,std::tuple<Ts>>...>;
};

// All elements >= P
template<unsigned P,typename T,typename I> struct TailImpl;
template<unsigned P,typename...Ts,std::size_t...Is>
struct TailImpl<P,List<Ts...>,std::index_sequence<Is...>>
{
    using type = TupleCat<
       std::conditional_t<(Is<P),std::tuple<>,std::tuple<Ts>>...>;
};

template<typename N,unsigned P,typename T,typename I>
struct InsertIntoListImpl
{
    using head = typename HeadImpl<P,T,I>::type;
    using tail = typename TailImpl<P,T,I>::type;
    using type = ListFromTupleCat<head,std::tuple<N>,tail>;
};

template<typename...Ts> struct List {
    /* ... */
    template<std::size_t P>
    using Remove =
      typename RemoveFromListImpl<P,List<Ts...>,
        std::index_sequence_for<Ts...>>::type;

    template<typename N,std::size_t P>
    using Insert =
      typename InsertIntoListImpl<N,P,List<Ts...>,
        std::index_sequence_for<Ts...>>::type;
};


static_assert(std::is_same
<
    List<int, char, float>::Remove<0>,
    List<char, float>
>(), "");

static_assert(std::is_same
<
    List<int, char, float>::Remove<1>,
    List<int, float>
>(), "");

static_assert(std::is_same
<
    List<int, char, float>::Insert<int, 0>,
    List<int, int, char, float>
>(), "");

static_assert(std::is_same
<
    List<int, char, float>::Insert<int, 2>,
    List<int, char, int, float>
>(), "");

int main(){}

Live example

关于c++ - 将类型插入/删除可变参数模板列表(参数包),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28434651/

相关文章:

python - 识别运行代码的类

c++ - 用于优化存储/运行时算法的元编程,C++

c++ - 从私有(private)构造函数/赋值运算符更改为删除会破坏二进制兼容性吗?

C++ 可变参数模板类型过滤转换

c++ - Qt:更新 QString 时自动生成的代码失败

c++ - 这个模板元编程片段到底发生了什么?

c++ - 在编译时遍历一棵树,使用访问操作

c++ - 图灵机 : But why use template metaprogramming?

C++ 字符串变量声明

c++ - 使用 C 或 C++ 制作自定义运行对话框?