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

标签 c++ templates c++11 variadic-templates

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

prog.cpp: In function ‘int main()’:
prog.cpp:24:22: error: incomplete type ‘remove_last<std::tuple<int, int> >’ used in nested name specifier
prog.cpp:24:22: error: incomplete type ‘remove_last<std::tuple<int, int> >’ used in nested name specifier
prog.cpp:24:70: error: template argument 1 is invalid

#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"
    );
}

当我在其中一个特化中将模板参数设置为非可变参数时,错误就消失了。但随后这就变成了一种特化,它只会处理一个包含两个元素的元组——这不是我的目标。我怎样才能让它与可变参数一起工作??换句话说,当元组中有多个元素时,我如何才能让它发挥作用?

最佳答案

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

您可以这样定义可变参数特化(注意参数包现在出现在 last in 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;
};

并且有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...>;
};

关于c++ - 尝试从元组中删除最后一个类型失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16268107/

相关文章:

c++ - cin 导致运行时错误

c++ - enable_if 模板特化自定义特征

c++ - 根据模板参数有条件地定义模板类的构造函数

C++11 lambda : member variable capture gotcha

c++ - 对齐的结构/类对象的填充字节中存储哪些值

c++ - OpenMP 从并行 for 循环调用并行函数

c++ - 另一个函数内的函数前向声明

c++ - 如何将模板类的内部类分离到其他文件中

c++11 - 单独的一次性代码路径

c++ - std::is_assignable 和 std::pair<const T, U>