如何从模板参数包中删除类型?

Nik*_*iou 11 c++ templates template-meta-programming variadic-templates c++11

我正在寻找一种方法来从模板参数包中删除(现在让我们说所有出现的)一个类型.最终结果将是一个如下所示的结构:

template<typename T, typename...Ts>
struct RemoveT
{
    using type = /* a new type out of Ts that does not contain T */
}
Run Code Online (Sandbox Code Playgroud)

假设边缘情况RemoveT<int, int>将通过返回来处理void(不在后面的代码中处理).我的初始设计看起来像这样:

// --------------------------------------------------------------
// 1. A "way" of typedefing variadic number of types ------------
template<typename...Ts>
struct pack { 
    using type = Ts; 
};
// --------------------------------------------------------------

// --------------------------------------------------------------
template<typename T, typename...Ts> struct RemoveT;

template<typename T, typename T1, typename...Ts>
struct RemoveT {
    using type = typename pack<T1, typename RemoveT<T, Ts...>::type>::type;
};

template<typename T, typename T1>
struct RemoveT<T, T1> { 
    using type = T1; 
};

template<typename T, typename...Ts>
struct RemoveT<T, T, Ts...> {
    using type = typename RemoveT<Ts...>::type;
};
// --------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

现在,我甚至不能开始测试该代码,因为pack结构是无效的C++

重述

以防万一这有助于回答,其他一些解决方案

  • 人们可能会说这pack根本不是有用的.我们可以在RemoveT结构周围移动,创建一个RemoveT只包含所需类型的新结构.然后,问题在从结构中提取类型时进行转换
  • 我们可以创建一个模仿的行为类型对类型串并采取一个更有递归方法.

底线

对于可变类型Ts和类型T:我可以创建Us出来的Ts省略T吗?

Dan*_*rey 10

以下提供了递归和非直接的方式来删除TTs...,就像Jarod42的解决方案,产生了std::tuple<Us...>无需使用,但typename ...::type:

#include <tuple>
#include <type_traits>

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

template<typename T, typename...Ts>
using remove_t = tuple_cat_t<
    typename std::conditional<
        std::is_same<T, Ts>::value,
        std::tuple<>,
        std::tuple<Ts>
    >::type...
>;


int main()
{
    static_assert(std::is_same<
        remove_t<int, int, char, int, float, int>,
        std::tuple<char, float>
    >::value, "Oops");
}
Run Code Online (Sandbox Code Playgroud)

实例


Jar*_*d42 8

以下可能有所帮助

namespace detail
{
    template <typename T, typename Tuple, typename Res = std::tuple<>>
    struct removeT_helper;


    template<typename T, typename Res>
    struct removeT_helper<T, std::tuple<>, Res>
    {
        using type = Res;
    };

    template<typename T, typename... Ts, typename... TRes>
    struct removeT_helper<T, std::tuple<T, Ts...>, std::tuple<TRes...>> :
        removeT_helper<T, std::tuple<Ts...>, std::tuple<TRes...>>
    {};

    template<typename T, typename T1, typename ...Ts, typename... TRes>
    struct removeT_helper<T, std::tuple<T1, Ts...>, std::tuple<TRes...>> :
        removeT_helper<T, std::tuple<Ts...>, std::tuple<TRes..., T1>>
    {};

}

template <typename T, typename...Ts> struct RemoveT
{
    using type = typename detail::removeT_helper<T, std::tuple<Ts...>>::type;
};

static_assert(std::is_same<std::tuple<char, float>,
                        typename RemoveT<int, int, char, int, float, int>::type>::value, "");
Run Code Online (Sandbox Code Playgroud)