可变模板递归

时间:2016-10-14 12:53:23

标签: c++11 templates recursion variadic-templates variadic

我正在尝试使用递归来解决这个问题,如果我调用

decimal<0,0,1>();

我应该得到十进制数(在这种情况下为4)。

我正在尝试使用可变参数模板进行递归,但无法使其工作。

这是我的代码;

template<>
int decimal(){
    return 0;
}



template<bool a,bool...pack>
int decimal(){
        cout<<a<<"called"<<endl;
        return a*2 + decimal<pack...>();
};

int main(int argc, char *argv[]){
    cout<<decimal<0,0,1>()<<endl;
    return 0;
}

解决这个问题的最佳方法是什么?

3 个答案:

答案 0 :(得分:3)

template<typename = void>
int decimal(){
    return 0;
}

template<bool a,bool...pack>
int decimal(){
        cout<<a<<"called"<<endl;
        return a + 2*decimal<pack...>();
};

问题在于递归情况,它希望能够调用decltype<>()。这就是我在上面的第一个重载中定义的内容。你基本上可以忽略typename=void,这是允许第一个编译的必要条件。

答案 1 :(得分:0)

一个可能的解决方案可以是使用constexpr函数(这样你就可以在适当的时候使用它值的运行时值),其中值是函数的参数。

这样的东西
#include <iostream>

constexpr int decimal ()
 { return 0; }

template <typename T, typename ... packT>
constexpr int decimal (T const & a, packT ... pack)
 { return a*2 + decimal(pack...); }

int main(int argc, char *argv[])
 {
   constexpr  int  val { decimal(0, 0, 1) };

   static_assert( val == 2, "!");

   std::cout << val << std::endl;

   return 0;
 }

但我获得2而不是4。

你确定你的代码应该返回4吗?

- 编辑 -

正如aschepler所指出的,我的示例decimal()模板函数返回&#34; eturns两倍于其参数的总和,而不是&#34;你想要什么。

好吧,01truefalse获得同样的结果;使用其他数字,您将获得不同的结果。

但您可以按如下方式修改decimal()

template <typename ... packT>
constexpr int decimal (bool a, packT ... pack)
 { return a*2 + decimal(pack...); }

避免这个问题。

答案 2 :(得分:0)

这是一个C ++ 14解决方案。除了std::integral_sequence nad std::index_sequence之外,它主要是C ++ 11,这两者在C ++ 11中都相对容易实现。

template<bool...bs>
using bools = std::integer_sequence<bool, bs...>;

template<std::uint64_t x>
using uint64 = std::integral_constant< std::uint64_t, x >;

template<std::size_t N>
constexpr uint64< ((std::uint64_t)1) << (std::uint64_t)N > bit{};

template<std::uint64_t... xs>
struct or_bits : uint64<0> {};

template<std::int64_t x0, std::int64_t... xs>
struct or_bits<x0, xs...> : uint64<x0 | or_bits<xs...>{} > {};

template<bool...bs, std::size_t...Is>
constexpr
uint64<
  or_bits<
    uint64<
      bs?bit<Is>:std::uint64_t(0)
    >{}...
  >{}
>
from_binary( bools<bs...> bits, std::index_sequence<Is...> ) {
  (void)bits; // suppress warning
  return {};
}


template<bool...bs>
constexpr
auto from_binary( bools<bs...> bits={} )
-> decltype( from_binary( bits, std::make_index_sequence<sizeof...(bs)>{} ) )
{ return {}; }

它会将结果值生成为constexpr转换为标量的类型。这在“编译时间”中比constexpr函数稍强一些。

它假定第一位是列表中最重要的位。

您可以使用from_binary<1,0,1>()from_binary( bools<1,0,1>{} )

Live example

这种基于类型的编程风格导致代码在其签名中完成所有工作。这些机构由return {};组成。