可变参数模板解压缩typename的参数

时间:2014-01-17 07:37:44

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

我想在func中解压缩参数包(参见第A行),但它不起作用。如何解压func< >或仅修改A行?

#include <iostream>
using namespace std;

void func()
{
   cerr << "EMPTY" << endl;
}

template <class A, class ...B> void func()
{
   cerr << "A: "  << endl;
   func<B... >(); // line A
}


int main(void)
{
   func<int,int>();
   return 0;
}

预期输出:

A:
A:

编辑: 所有答案都非常好。非常感谢

4 个答案:

答案 0 :(得分:12)

有时一次解包所有内容更容易,而不是递归。如果您只想要参数包for_each,则可以使用the braced-init-list expansion trickLive demo at Coliru)的变体:

template <class A>
void process_one_type() {
    cerr << typeid(A).name() << ' ';
}

template <class ...B> void func()
{
    int _[] = {0, (process_one_type<B>(), 0)...};
    (void)_;
    cerr << '\n';
}

答案 1 :(得分:10)

使用func<B... >();表示func是一个功能模板,但之前定义的func()不是。

您需要定义一个接受模板参数的func()模板。这是一个工作示例(在g ++ 4.8.1上):

#include <iostream>
using namespace std;

void func()
{
   cerr << "EMPTY" << endl;
}

template <class ... B>
typename std::enable_if<sizeof...(B) == 0>::type func()
{
}

template <class A, class ...B> void func()
{
   cerr << "A: "  << endl;
   func<B... >(); // line A
}


int main(void)
{
   func();           // This outputs EMPTY
   func<int,int>();  // This will not output EMPTY
   return 0;
}

答案 2 :(得分:7)

试试这个:

template <class A> void func()
{
    cerr << "A: " << endl;
}

template <class A, class B, class ...C> void func()
{
    cerr << "A: " << endl;
    func<B, C...>(); // line A
}

答案 3 :(得分:2)

考虑当func<B...>();为空时递归调用B...的调用是什么。它正在调用func<>();,但您尝试的基本情况func()的定义不是模板函数,即。你不能通过func<>();

来调用它

由于我们尚未对函数模板进行部分特化,(希望很快就会支持它),一种方法是使用类模板进行部分特化并使用函数简单地将工作委托给课堂模板。

#include <iostream>

/* Forward declaration. */
template <typename... T>
struct FuncImpl;

/* Base case. */
template <>
struct FuncImpl<> {

  void operator()() const {
    std::cout << "Base case" << std::endl;
  }

};  // FuncImpl<>

/* Recursive case. */
template <typename First, typename... Rest>
struct FuncImpl<First, Rest...> {

  void operator()() const {
    std::cout << "Recursive case" << std::endl;
    FuncImpl<Rest...>()();
  }

};  // FuncImpl<First, Rest...>

/* Delegate function. */
template <typename... T>
void Func() {
  FuncImpl<T...>()();
}

int main() {
  Func<>();
  Func<int, double>();
}

我个人认为这个解决方案比其他解决方案更清晰,例如标记调度或SFINAE,尽管operator()周围存在争议。