尝试从元组中删除最后一个类型失败

0x4*_*2D2 7 c++ templates variadic-templates c++11

我正在尝试删除元组的最后一个元素.当我在元组中只有一个元素要移除时,它可以工作.但是当我不止一个时,事情就出错了.我不明白为什么这不起作用.这些是我得到的错误:

prog.cpp:在函数' int main()':
prog.cpp:24:22:错误:不完整类型' remove_last<std::tuple<int, int> >'用于嵌套名称说明符
prog.cpp:24:22:错误:不完整类型' remove_last<std::tuple<int, int> >'用于嵌套名称说明符
prog.cpp :24:70:错误:模板参数1无效

#include <tuple>
#include <type_traits>

template <class T>
struct remove_last;

template <class T>
struct remove_last<std::tuple<T>>
{
    using type = std::tuple<>;
};

template <class... Args, typename T>
struct remove_last<std::tuple<Args..., T>>
{
    using type = std::tuple<Args...>;
};

int main()
{
    std::tuple<int, int> var;

    static_assert(
        std::is_same<remove_last<decltype(var)>::type,
        std::tuple<int>>::value, "Values are not the same"
    );
}
Run Code Online (Sandbox Code Playgroud)

当我在其中一个特化中使模板参数非变量时,错误消失了.但后来这变成了一个专门化,它只会处理一个有两个元素的元组 - 而不是我的目标.如何使用可变参数进行此操作?换句话说,当元组中有多个元素时,如何才能使它工作?

And*_*owl 6

问题是参数包是贪婪的 - 并且 - 因为它是第一个 - 在执行类型推导时吃掉序列中的所有类型,包括T你希望被排除在外的类型Args....

您可以通过这种方式定义可变参数化特征(注意参数包现在出现在最后std::tuple<T, Args...>):

template <class T, class... Args>
struct remove_last<std::tuple<T, Args...>>
{
    using type = typename concat_tuple<
        std::tuple<T>,
        typename remove_last<std::tuple<Args...>>::type
        >::type;
};
Run Code Online (Sandbox Code Playgroud)

并以concat_tuple这种方式定义元函数:

template<typename, typename>
struct concat_tuple { };

template<typename... Ts, typename... Us>
struct concat_tuple<std::tuple<Ts...>, std::tuple<Us...>>
{
    using type = std::tuple<Ts..., Us...>;
};
Run Code Online (Sandbox Code Playgroud)