Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 获取参数包的前N个元素_C++_C++14_Variadic Templates - Fatal编程技术网

C++ 获取参数包的前N个元素

C++ 获取参数包的前N个元素,c++,c++14,variadic-templates,C++,C++14,Variadic Templates,我必须解决以下问题: template< size_t... N_i > class A { // ... }; template< size_t N, size_t... N_i > A</* first N elements of N_i...*/> foo() { A</* first N elements of N_i...*/> a; // ... return a; } int main() { A<1

我必须解决以下问题:

template< size_t... N_i >
class A
{
  // ...
};

template< size_t N, size_t... N_i >
A</* first N elements of N_i...*/> foo()
{
  A</* first N elements of N_i...*/> a;

  // ...

  return a;
}

int main()
{
  A<1,2> res = foo<2, 1,2,3,4>();

  return 0;
}
模板
甲级
{
// ...
};
模板<大小\u t N,大小\u t。。。N_i>
阿福()
{
A A;
// ...
返回a;
}
int main()
{
A res=foo();
返回0;
}
这里,我希望
foo
具有返回类型
A
,即
类A
,它具有参数包
N\u I
的前N个元素作为模板参数


有人知道如何实现吗?

不幸的是,这种方法需要定义额外的助手类型

template< size_t... N_i >
class A
{
};

template <size_t... N_i>
struct Helper;

template <size_t... N_i>
struct Helper<0, N_i...>
{
    typedef A<> type;
};

template <size_t N0, size_t... N_i>
struct Helper<1, N0, N_i...>
{
    typedef A<N0> type;
};

template <size_t N0, size_t N1, size_t... N_i>
struct Helper<2, N0, N1, N_i...>
{
    typedef A<N0, N1> type;
};

template< size_t N, size_t... N_i >
typename Helper<N, N_i...>::type foo()
{
  typename Helper<N, N_i...>::type a;
  return a;
}
模板
甲级
{
};
模板
结构助手;
模板
结构辅助程序
{
类型定义类型;
};
模板
结构辅助程序
{
类型定义类型;
};
模板
结构辅助程序
{
类型定义类型;
};
模板<大小\u t N,大小\u t。。。N_i>
typename助手::类型foo()
{
typename助手::类型a;
返回a;
}

最直接的子问题是类型列表:

template <class... Ts>
struct typelist {
    using type = typelist;
    static constexpr std::size_t size = sizeof...(Ts);
};

template <class T>
struct tag { using type = T; };

template <std::size_t N, class TL>
struct head_n {
    using type = ???;
};
从这个问题到你的具体问题,我留给读者作为练习


另一种方法是通过连接。将
类型列表
中的每个元素转换为
类型列表
类型列表
,然后将它们合并在一起<代码>concat非常简单:

template <class... Ts>
struct concat { };

template <class TL>
struct concat<TL>
: tag<TL>
{ };

template <class... As, class... Bs, class... Rest>
struct concat<typelist<As...>, typelist<Bs...>, Rest...>
: concat<typelist<As..., Bs...>, Rest...>
{ };
允许:

template <std::size_t N, class... Ts, std::size_t... Is>
struct head_n<N, typelist<Ts...>, std::index_sequence<Is...>>
{
    using type = decltype(
        (std::conditional_t<(Is < N), typelist<Ts>, typelist<>>{} + ... + typelist<>{})
        );
};        
模板
结构头
{
使用type=decltype(
(std::conditional_t{}+…+类型列表{})
);
};        

这非常简单:

namespace-hana=boost::hana;
模板
自动生成(hana::元组)
{
返回一个{};
}
模板
自动foo(){
constexpr auto-front=hana::向前走(
hana::元组c,
hana::积分
);
退货明细:make_a(正面);
}

这是我想到的最短解决方案(一个别名用了两行)。
下面是一个基于OP发布的代码的最小的工作示例:

#include<functional>
#include<cstddef>
#include<utility>
#include<tuple>

template<std::size_t... V>
class A {};

template<std::size_t... V, std::size_t... I>
constexpr auto func(std::index_sequence<I...>) {
    return A<std::get<I>(std::make_tuple(V...))...>{};
}

template<std::size_t N, std::size_t... V>
constexpr auto func() {
    return func<V...>(std::make_index_sequence<N>{});
}

template<std::size_t N, std::size_t... V>
using my_a = decltype(func<N, V...>());

int main() {
    A<1,2> res1 = func<2, 1, 2, 3, 4>();
    // Or even better...
    decltype(func<2, 1, 2, 3, 4>()) res2{};
    // Or even better...
    my_a<2, 1, 2, 3, 4> res3{};
}
#包括
#包括
#包括
#包括
模板
A类{};
模板
constexpr自动函数(std::index_序列){
返回一个{};
}
模板
constexpr auto func(){
返回func(std::make_index_sequence{});
}
模板
使用my_a=decltype(func());
int main(){
A res1=func();
//或者更好。。。
decltype(func())res2{};
//或者更好。。。
我的{u a res3};
}

您还可以使用可变的通用lambda表达式和可重用的helper结构来执行编译时迭代:

#include <utility>
#include <tuple>

template <std::size_t N, class = std::make_index_sequence<N>>
struct iterate;

template <std::size_t N, std::size_t... Is>
struct iterate<N, std::index_sequence<Is...>> {
   template <class Lambda>
   auto operator()(Lambda lambda) {
      return lambda(std::integral_constant<std::size_t, Is>{}...);
   }
};

template <size_t... Is>
struct A { };

template <size_t N, size_t... Is>
auto foo() {
   return iterate<N>{}([](auto... ps){
      using type = std::tuple<std::integral_constant<std::size_t, Is>...>;
      return A<std::tuple_element_t<ps, type>{}...>{};
   });
}

int main() {
   decltype(foo<3, 1, 2, 3, 4>()) a; // == A<1, 2, 3> a;
}
#包括
#包括
模板
结构迭代;
模板
结构迭代{
模板
自动运算符()(Lambda Lambda){
返回lambda(std::积分常数{};
}
};
模板
结构A{};
模板
自动foo(){
返回迭代{}([](自动…ps){
使用type=std::tuple;
返回一个{};
});
}
int main(){
decltype(foo())a;//==a;
}

这是上的一个细微变化,可避免使用元组:

template <size_t... N_i,size_t... M_i>
auto foo2(std::index_sequence<M_i...>)
{
    constexpr size_t values[] = {N_i...};
    return A<values[M_i]...>();
}

template <size_t N,size_t... N_i>
auto foo()
{
    return foo2<N_i...>(std::make_index_sequence<N>());
}
模板
自动foo2(std::index\u序列)
{
constexpr size_t值[]={N_i…};
返回A();
}
模板
自动foo()
{
返回foo2(std::make_index_sequence());
}

有很多重复,谢谢。难道没有“优雅”的解决方案吗?@ AbraMaHiHiBelt:你正在做C++模板元编程,你想要一个“优雅”的解决方案吗?(有时这不是不可能的;)@krzaq可能这次也不是不可能这是
constepr
的一个很好的用法
make\u tuple
get
@krzaq谢谢你。希望这对OP有所帮助。@skypjack顺便说一句,我实际上认为这个解决方案一点也不棘手,而且可能非常可扩展:)请不要误解,我喜欢您将默认参数、部分专门化和lambda函数组合在一起的方式。我只是觉得这对具体案件来说太棘手了。我是该党的一员,如果你能排成一行,你就不应该浪费下面这一行。这就是全部。无论如何,这是一个不错的解决方案。;-)我两三个评论前就收到了-D我明白你的意思,但我想你还是可以写得更简洁一些。不管怎么说,我喜欢这个,因为它是一个大脑健身房@skypjack hah brain gym我必须记住:)你把我和聚会的
搞混了,如果你能排成一行,你就不应该浪费下面的一条
评论:)老实说,我也认为你的解决方案对OP来说可能是最好的,但是将来可能有人会在他或她的特定问题中发现更好的代码:)您可以将
decltype(ps)::value
简化为
ps
。而整个
tuple_元素
stuff到
A{}
你在你的细微变化中遗漏了一些东西。因为它不能再在常量表达式中使用。您应该在函数前面添加一个
constexpr
。如果你决定复制一个答案,请一直复制到最后。;-)
namespace hana = boost::hana;

template<size_t... vals>
auto make_a(hana::tuple<hana::integral_constant<size_t, vals>...>)
{
    return A<vals...>{};
}

template<size_t N, size_t... vals>
auto foo(){
    constexpr auto front = hana::take_front(
        hana::tuple_c<size_t, vals...>,
        hana::integral_c<size_t,N>
    );
    return detail::make_a(front);
}
#include<functional>
#include<cstddef>
#include<utility>
#include<tuple>

template<std::size_t... V>
class A {};

template<std::size_t... V, std::size_t... I>
constexpr auto func(std::index_sequence<I...>) {
    return A<std::get<I>(std::make_tuple(V...))...>{};
}

template<std::size_t N, std::size_t... V>
constexpr auto func() {
    return func<V...>(std::make_index_sequence<N>{});
}

template<std::size_t N, std::size_t... V>
using my_a = decltype(func<N, V...>());

int main() {
    A<1,2> res1 = func<2, 1, 2, 3, 4>();
    // Or even better...
    decltype(func<2, 1, 2, 3, 4>()) res2{};
    // Or even better...
    my_a<2, 1, 2, 3, 4> res3{};
}
#include <utility>
#include <tuple>

template <std::size_t N, class = std::make_index_sequence<N>>
struct iterate;

template <std::size_t N, std::size_t... Is>
struct iterate<N, std::index_sequence<Is...>> {
   template <class Lambda>
   auto operator()(Lambda lambda) {
      return lambda(std::integral_constant<std::size_t, Is>{}...);
   }
};

template <size_t... Is>
struct A { };

template <size_t N, size_t... Is>
auto foo() {
   return iterate<N>{}([](auto... ps){
      using type = std::tuple<std::integral_constant<std::size_t, Is>...>;
      return A<std::tuple_element_t<ps, type>{}...>{};
   });
}

int main() {
   decltype(foo<3, 1, 2, 3, 4>()) a; // == A<1, 2, 3> a;
}
template <size_t... N_i,size_t... M_i>
auto foo2(std::index_sequence<M_i...>)
{
    constexpr size_t values[] = {N_i...};
    return A<values[M_i]...>();
}

template <size_t N,size_t... N_i>
auto foo()
{
    return foo2<N_i...>(std::make_index_sequence<N>());
}