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