Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/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++ 变元模板函数中不同参数类型的递归_C++_Arguments_Variadic Templates_Variadic Functions - Fatal编程技术网

C++ 变元模板函数中不同参数类型的递归

C++ 变元模板函数中不同参数类型的递归,c++,arguments,variadic-templates,variadic-functions,C++,Arguments,Variadic Templates,Variadic Functions,考虑下面的代码 template <int INDEX> void foo() { } // termination version template <int INDEX, typename Arg, typename... Args> void foo(Arg head, Args... args) { if (INDEX == 0) { cout << head << endl; } else

考虑下面的代码

template <int INDEX>
void foo() {  } // termination version

template <int INDEX, typename Arg, typename... Args>
void foo(Arg head, Args... args) {

    if (INDEX == 0) {


        cout << head << endl;
    }

   else {


        foo <INDEX-1 > (args...);

   }

}

int main() {

   foo<1> (1, 3.1415);

   return 0;
}
模板
void foo(){}//终止版本
模板
无效foo(Arg头,Args…Args){
如果(索引==0){

我认为(至少在C++11和C++14中)不可能开发这种类型的
foo()
,因为您不知道正确的返回类型

如果您不想使用
std::tuple
,我建议开发一个类型traits来提取第n个类型,并通过SFINAE管理
foo()

下面是一个可能的解决方案

#include <iostream>
#include <type_traits>

template <std::size_t, typename...>
struct indexType
 { using type = int; }; // the type of the foo() without argument

template <std::size_t I, typename I0, typename ... Is>
struct indexType<I, I0, Is...>
 { using type = typename indexType<I-1U, Is...>::type; };

template <typename I0, typename ... Is>
struct indexType<0U, I0, Is...>
 { using type = I0; };

template <std::size_t I, typename ... Args>
using indexType_t = typename indexType<I, Args...>::type;


template <std::size_t>
int foo ()
 { return 0;  } // termination version: a return type is needed


template <std::size_t I, typename Arg, typename... Args>
auto foo (Arg const & head, Args const & ...)
   -> typename std::enable_if<I == 0U, Arg>::type
 { return head; }

template <std::size_t I, typename Arg, typename... Args>
auto foo (Arg const &, Args const & ... args)
   -> typename std::enable_if<I != 0U, indexType_t<I-1U, Args...>>::type
 { return foo<I-1U>(args...); }

int main ()
 {
   std::cout << foo<1U> (1, 3.1415, std::string("Test!")) << std::endl;
   std::cout << foo<2U> (1, 3.1415, std::string("Test!")) << std::endl;
   std::cout << foo<3U> (1, 3.1415, std::string("Test!")) << std::endl;
 }
#包括
#包括
模板
结构索引类型
{using type=int;};//不带参数的foo()的类型
模板
结构索引类型
{using type=typename indexType::type;};
模板
结构索引类型
{使用类型=I0;};
模板
使用indexType_t=typename indexType::type;
模板
int foo()
{return 0;}//终止版本:需要返回类型
模板
自动foo(参数常量和头,参数常量和头)
->typename std::enable_if::type
{返回头;}
模板
自动foo(参数常量&,参数常量&…参数)
->typename std::enable_if::type
{返回foo(args…)}
int main()
{
std::你的方法可能有问题
1.1在
foo
确保您了解嵌套调用的
返回如何工作。您的
foo
调用
foo
,它将其(
foo
)第一个参数返回到
foo
。但是您的
foo
不关心
foo
的返回,因为它调用了
foo
,如下所示:

else {
    foo<i-1>(args...);// `i-1` becomes `0`
}
1.2必须在编译时知道返回类型 您可以尝试通过将
foo
中的返回值向上传递来修复代码:

else {
    return foo<i-1>(args...);// NOTE: type of return value depends on `foo<i-1>`
}
2.2 C++14及以上版本 使用C++14,您也可以使用
auto
作为返回类型,但如果
不可用,则使用
constexpr。解决方法是一种众所周知的习惯用法,使用“实现”递归逻辑的类模板的专门化:

template<int i>
struct foo_impl {
  static_assert(i > 0, "the case `i == 0` requires a specialization");

  template<class T0, class... Ts>
  static auto get(T0, Ts... vs) {
    return foo_impl<i-1>::get(vs...);
  }
};

template<>
struct foo_impl<0> {
  template<class T0, class... Ts>
  static auto get(T0 v0, Ts...) {
    return v0;
  }
};

template<int i, class... Ts>
auto foo(Ts... vs) {
  static_assert(i >= 0 && i < sizeof...(Ts), "index range: [0, size)");
  return foo_impl<i>::get(vs...);// forward to "implementation"
}
模板
结构foo_impl{
static_assert(i>0,“i==0”需要专门化);
模板
静态自动获取(T0,Ts…vs){
返回foo_impl::get(vs.);
}
};
模板
结构foo_impl{
模板
静态自动获取(T0 v0,Ts…){
返回v0;
}
};
模板
自动foo(Ts…vs){
静态断言(i>=0&&i
2.3 C++11及以上版本 对于C++11,您需要指定有点繁琐的尾部返回类型。有关详细信息,请参阅

3最后建议
  • 启用并分析编译器警告(
    -Wall
    是绝对最小值)
  • 一旦您熟悉了这些技术,就不要自己实现它。相反,请学习并使用标准解决方案,如
    std::tuple
  • 小心使用编译时递归。它可能会显著增加编译时间

请启用编译器警告。并非所有路径都返回…->格式错误的代码。
返回std::get(std::forward\u as\u tuple(args…)
?您知道如何解决此问题吗?其思想是函数可以处理一组不相关的参数,并以参数类型返回一些结果。Thankx。我知道tuple,但我想自己实现几行。比您更有用。
else {
    return foo<i-1>(args...);// NOTE: type of return value depends on `foo<i-1>`
}
template<int i, class Arg, class... Args>
Arg foo(Arg, Args... args) {// <--------- NOTE: must return a value of type `Arg`
template<size_t i, class T0, class... Ts>
auto foo(T0 v0, Ts... vs) {
  static_assert(i < 1u + sizeof...(Ts));
  if constexpr(0u == i) return v0;// <------ NOTE: must be `if constexpr` (C++17)
  else return foo<i-1u>(vs...);
}
template<int i>
struct foo_impl {
  static_assert(i > 0, "the case `i == 0` requires a specialization");

  template<class T0, class... Ts>
  static auto get(T0, Ts... vs) {
    return foo_impl<i-1>::get(vs...);
  }
};

template<>
struct foo_impl<0> {
  template<class T0, class... Ts>
  static auto get(T0 v0, Ts...) {
    return v0;
  }
};

template<int i, class... Ts>
auto foo(Ts... vs) {
  static_assert(i >= 0 && i < sizeof...(Ts), "index range: [0, size)");
  return foo_impl<i>::get(vs...);// forward to "implementation"
}