C++11 通过弹出最后一个类型创建新的元组类

C++11 通过弹出最后一个类型创建新的元组类,c++11,variadic-templates,C++11,Variadic Templates,我尝试了以下代码,但它给出: main.cpp:29:22:错误:聚合'pop'的类型不完整,无法定义 我错过了什么 template <typename T> struct pop; template <typename E, typename... Ts> struct pop<tuple<Ts..., E>> { using result = tuple<Ts...>; }; tuple<int, char, f

我尝试了以下代码,但它给出:

main.cpp:29:22:错误:聚合
'pop'
的类型不完整,无法定义

我错过了什么

template <typename T>
struct pop;

template <typename E, typename... Ts>
struct pop<tuple<Ts..., E>> {
    using result = tuple<Ts...>;
};

tuple<int, char, float> t;
typename pop<decltype(t)>::result p;
模板
结构pop;
模板
结构弹出{
使用结果=元组;
};
元组t;
typename-pop::结果p;
如果。。。必须位于类型列表的末尾,为什么在本例中它从以下位置起作用:

模板无效函数(A arg1、B arg2、C…arg3)
{
container t1;//展开为container
container t2;//展开为container
container t3;//扩展到container
}

Ts..
必须是类型列表中的最后一个元素,如果要对其进行推断<代码>元组不会推断出
Ts..
是最后一个,但决不会匹配任何内容

摆脱最后一个论点有点骗人

可以理解为
bob
is
foo
。另一种选择是更加冗长

template<class X>
struct bob {
  using type = typename foo<X>::type;
};
模板
结构鲍勃{
使用type=typename foo::type;
};
展开变量类型列表不同于匹配它们。在设计时,匹配保持简单,以使编译器供应商能够实现该功能。在这条道路上,除了“这很棘手”之外,可能还有一些棘手的问题。

tuple
是一个非演绎的上下文。[临时扣减类型]/9:

如果
p
的表单包含
,则将相应模板参数列表
p
的每个参数
i与
a
的相应模板参数列表的相应参数
a
i进行比较如果
P
的模板参数列表包含不是最后一个模板参数的包扩展,则整个模板参数列表为非推断上下文。

这意味着你的部分专业化从未匹配过

使用C++14,可以使用

template <class T, class=std::make_index_sequence<std::tuple_size<T>::value-1>>
struct pop;

template <typename Tuple, std::size_t... indices>
struct pop<Tuple, std::index_sequence<indices...>>
{
    using type = std::tuple<std::tuple_element_t<indices, Tuple>...>;
};

template <typename T>
using pop_t = typename pop<T>::type;
模板
结构pop;
模板
结构弹出
{
使用type=std::tuple;
};
模板
使用pop_t=typename-pop::type;
以致

using t = std::tuple<int, char, float>;
static_assert( std::is_same<pop_t<t>, std::tuple<int, char>>{}, "" );
使用t=std::tuple;
静态断言(std::is_same{},“”;
编译


.

这是我提出的解决方案:

template <typename T>
struct pop;

template <typename E, typename... Ts>
struct pop<std::tuple<E, Ts...>> {
    using type = decltype(tuple_cat(
        declval<tuple<E>>(),
        declval<typename pop<tuple<Ts...>>::type>()
    ));
};

template <typename E>
struct pop<std::tuple<E>> {
    using type = std::tuple<>;
};
模板
结构pop;
模板
结构弹出{
使用type=decltype(元组)(
declval(),
declval()
));
};
模板
结构弹出{
使用type=std::tuple;
};

另一种C++11剥猫皮的方法:

#include <tuple>

template<class Tuple>
struct pop;

template<>
struct pop<std::tuple<>>
{
    using type = std::tuple<>;
};

template<typename T1>
struct pop<std::tuple<T1>>
{
    using type = std::tuple<>;
};

template<typename First, typename... Rest>
struct pop<std::tuple<First,Rest...>>
{
    using type = 
    decltype(std::tuple_cat(
                std::declval<std::tuple<First>>(),
                std::declval<typename pop<std::tuple<Rest...>>::type>()));
};

// Test...

static_assert(std::is_same<pop<std::tuple<>>::type,std::tuple<>>::value,"");
static_assert(std::is_same<pop<std::tuple<int>>::type,std::tuple<>>::value,"");
static_assert(
    std::is_same<pop<std::tuple<int,char>>::type,std::tuple<int>>::value,"");
static_assert(
    std::is_same<pop<std::tuple<int,char,float>>::type,
        std::tuple<int,char>>::value,"");
static_assert(
    std::is_same<pop<std::tuple<int,char,float,double>>::type,
        std::tuple<int,char,float>>::value,"");
#包括
模板
结构pop;
模板
结构弹出
{
使用type=std::tuple;
};
模板
结构弹出
{
使用type=std::tuple;
};
模板
结构弹出
{
使用类型=
decltype(std::tuple_cat)(
std::declval(),
std::declval());
};
//测试。。。
静态断言(std::is_same::value,“”);
静态断言(std::is_same::value,“”);
静态断言(
std::is_same::value“”;
静态断言(
std::is_same::value“”;
静态断言(
std::is_same::value“”;

这将从
tuple
创建
tuple
,我怀疑这是您的意图。您可以尝试一种基于
decltype(tuple_cat
的解决方案?为了清楚起见,我认为这解决了上述问题:
template struct pop;template struct pop{using type=std::tuple_cat\t;templatestruct pop{using type=std::tuple;};
@Yakk谢谢,我更正了答案。我认为答案不应该再被否决了。
在标题中使用名称空间std;
是一个非常糟糕的主意(取决于标题包含顺序,它可能会导致代码做不同的事情!),和
template
s类似于上面的活在标题中。还修复了
cat
语句--
\u t
::type
不住在一起。使用
typename
@Yakk将其改为C++11。我认为这仍然是错误的。tuple\u cat()似乎是返回连接元组类型实例的函数。我的意思是它应该是
使用type=decltype(tuple_cat(declval(),declval());
,对吗?梵蒂冈想和你谈谈…(标题编辑)回答得很好……那么,用c++11怎么解决呢?@bmm您基本上必须使用
typename std::tuple\u element::type
作为扩展模式,并编写自己的
make\u index\u sequence
(这是几行代码)如果你想要的话,我将把它集成到答案中。这是一个很好的事情,它有一个恒定的模板实例化深度:在C++中是一个有限的资源,所以节约是好的,并且限制它会减少编译时内存的需求和时间。伊利。真是太遗憾了。哇,这是一个聪明的解决方案!!
pop
专业化没有被
pop
涵盖吗?
using t = std::tuple<int, char, float>;
static_assert( std::is_same<pop_t<t>, std::tuple<int, char>>{}, "" );
template <typename T>
struct pop;

template <typename E, typename... Ts>
struct pop<std::tuple<E, Ts...>> {
    using type = decltype(tuple_cat(
        declval<tuple<E>>(),
        declval<typename pop<tuple<Ts...>>::type>()
    ));
};

template <typename E>
struct pop<std::tuple<E>> {
    using type = std::tuple<>;
};
#include <tuple>

template<class Tuple>
struct pop;

template<>
struct pop<std::tuple<>>
{
    using type = std::tuple<>;
};

template<typename T1>
struct pop<std::tuple<T1>>
{
    using type = std::tuple<>;
};

template<typename First, typename... Rest>
struct pop<std::tuple<First,Rest...>>
{
    using type = 
    decltype(std::tuple_cat(
                std::declval<std::tuple<First>>(),
                std::declval<typename pop<std::tuple<Rest...>>::type>()));
};

// Test...

static_assert(std::is_same<pop<std::tuple<>>::type,std::tuple<>>::value,"");
static_assert(std::is_same<pop<std::tuple<int>>::type,std::tuple<>>::value,"");
static_assert(
    std::is_same<pop<std::tuple<int,char>>::type,std::tuple<int>>::value,"");
static_assert(
    std::is_same<pop<std::tuple<int,char,float>>::type,
        std::tuple<int,char>>::value,"");
static_assert(
    std::is_same<pop<std::tuple<int,char,float,double>>::type,
        std::tuple<int,char,float>>::value,"");