Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.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++11中递归元函数的延迟返回类型解析_C++_Templates_C++11_Template Meta Programming - Fatal编程技术网

C++11中递归元函数的延迟返回类型解析

C++11中递归元函数的延迟返回类型解析,c++,templates,c++11,template-meta-programming,C++,Templates,C++11,Template Meta Programming,我试图用C++11编写一个简单的序列生成器,它接受一些开始和结束索引,并在编译时生成一个整数序列。由于integer_序列在C++14之前不可用,因此我使用自定义可变模板容器来存储integer序列: template <int...> struct IntSequence {}; #include <cstddef> template <size_t... Ints> struct integer_sequence { }; template <

我试图用C++11编写一个简单的序列生成器,它接受一些开始和结束索引,并在编译时生成一个整数序列。由于integer_序列在C++14之前不可用,因此我使用自定义可变模板容器来存储integer序列:

template <int...>
struct IntSequence {};
#include <cstddef>

template <size_t... Ints> struct integer_sequence { };

template <size_t begin, size_t end, size_t... ints>
struct integer_sequence_type { 
  using type = typename integer_sequence_type<begin+1, end, ints..., begin>::type;
};

template <size_t begin, size_t... ints>
struct integer_sequence_type<begin, begin, ints...> { 
  using type = integer_sequence<ints..., begin>;
};

// below part is for verification - compiler will tell you exactly the type :)
void foo(int );
void foo(char );

void test() {
  foo(integer_sequence_type<4, 8>::type());
}
template<class Seq, std::size_t Offset>
struct transform_seq;

template <std::size_t... Seq, std::size_t Offset>
struct transform_seq<seq<Seq...>, Offset>
{
    using type = seq<Seq+Offset...>;
};

template<std::size_t From, std::size_t To>
using sequence_generator = typename transform_seq<GenSeq<To-From+1>, From>::type;
这里我希望t是一个整数序列。我递归展开序列生成器,并使用enable_if停止递归:

template <int S, int E, int... Seq>
auto sequence_generator() -> enable_if_t<(S <= E), IntSequence<Seq...>> {
// Pack S into the variadic sequence and increment to S+1.  
return sequence_generator<S + 1, E, S, Seq...>();
}

template <int S, int E, int... Seq>
auto sequence_generator() -> enable_if_t<!(S <= E), IntSequence<Seq...>> {
  return IntSequence<Seq...>{};
}

但是,我的enable_if的构造函数不正确,因为我正在使用当前递归步骤中可用的变量包声明一个返回类型。相反,我希望编译器展开整个递归链,并选择基本情况的返回类型,即IntSequence。我不知道如何实现这一点。

以下是如何推断整数序列的实际类型:

template <int...>
struct IntSequence {};
#include <cstddef>

template <size_t... Ints> struct integer_sequence { };

template <size_t begin, size_t end, size_t... ints>
struct integer_sequence_type { 
  using type = typename integer_sequence_type<begin+1, end, ints..., begin>::type;
};

template <size_t begin, size_t... ints>
struct integer_sequence_type<begin, begin, ints...> { 
  using type = integer_sequence<ints..., begin>;
};

// below part is for verification - compiler will tell you exactly the type :)
void foo(int );
void foo(char );

void test() {
  foo(integer_sequence_type<4, 8>::type());
}
template<class Seq, std::size_t Offset>
struct transform_seq;

template <std::size_t... Seq, std::size_t Offset>
struct transform_seq<seq<Seq...>, Offset>
{
    using type = seq<Seq+Offset...>;
};

template<std::size_t From, std::size_t To>
using sequence_generator = typename transform_seq<GenSeq<To-From+1>, From>::type;

现在您可以使用这个构造来计算函数的返回类型。注意:我没有研究您的函数,因为您没有要求它。首先,让我们将SFINAE与返回类型扣除分开

template <int S, int E, int... Seq, std::enable_if_t<(S <= E), int>* =nullptr>
auto sequence_generator() -> ???
因为为什么要重复我们自己

在我们合成返回类型时可见的函数是在此函数模板之前声明的函数,以及通过ADL找到的任何函数

这一套不包括我们自己

因此,我们将创建一个详细名称空间,并强制ADL如下所示:

namespace details {
  struct helper {};

  template <int S, int E, int... Seq, std::enable_if_t<(S <= E), int>* =nullptr>
  auto sequence_generator(helper, IntSequence<S,E,Seq...>)
  -> ???
  {
    return {};
  }
  ???
}
template<int S, int E, int...Seq>
auto sequence_generator()
-> decltype( sequence_generator(details::helper{}, IntSequence<S,E,Seq...>{}) )
{
  return {};
}
我们现在必须执行这两项职能

  template <int S, int E, int... Seq, std::enable_if_t<(S <= E), int>* =nullptr>
  auto sequence_generator(helper, IntSequence<S,E,Seq...>)
  -> decltype( sequence_generator(helper{}, IntSequence<S + 1, E, S, Seq...>{}) );

  template <int S, int E, int... Seq, std::enable_if_t<(S > E), int>* =nullptr>
  auto sequence_generator(helper, IntSequence<S,E,Seq...>)
  -> IntSequence<Seq...>;
请注意,我将所有内容作为参数传递,并从中推断模板参数。这允许adl正常工作


另一种方法是不使用辅助函数直接构造类型;我假设您使用函数构造类型是出于您自己的原因。基于函数的模板元编程有很多优点;看看你能走多远。还有一些缺点,例如,为了递归返回类型,您必须运行ADL环。

最好的方法是从一个正常的索引序列实现开始,例如从序列执行和从序列转换:

template <int...>
struct IntSequence {};
#include <cstddef>

template <size_t... Ints> struct integer_sequence { };

template <size_t begin, size_t end, size_t... ints>
struct integer_sequence_type { 
  using type = typename integer_sequence_type<begin+1, end, ints..., begin>::type;
};

template <size_t begin, size_t... ints>
struct integer_sequence_type<begin, begin, ints...> { 
  using type = integer_sequence<ints..., begin>;
};

// below part is for verification - compiler will tell you exactly the type :)
void foo(int );
void foo(char );

void test() {
  foo(integer_sequence_type<4, 8>::type());
}
template<class Seq, std::size_t Offset>
struct transform_seq;

template <std::size_t... Seq, std::size_t Offset>
struct transform_seq<seq<Seq...>, Offset>
{
    using type = seq<Seq+Offset...>;
};

template<std::size_t From, std::size_t To>
using sequence_generator = typename transform_seq<GenSeq<To-From+1>, From>::type;

可以查看结果。

请。您对模板的参数可能有问题。这是最小的、完整的和可验证的!你想让我去掉什么?我想我很懒,想要把所有的东西都放在一个地方,或者一个链接到一个在线示例。如果没有C++14,你怎么使用enable_if__t?MSVC?我刚刚在我的源代码中添加了这个:使用enable_if_t=typename std::enable_if::type;