简体   繁体   English

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

[英]variadic template unpacking arguments to typename

I want to unpack the parameter pack in func (see line A), but it doesnt work. 我想在func解压缩参数包(参见第A行),但它不起作用。 How can I unpack inside func< > or modify Line A only? 如何在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;
}

An expected output : 预期输出:

A:
A:

edited: all of answers are very good. 编辑:所有答案都非常好。 thanks alot 非常感谢

Sometimes it's easier to unpack everything at once, instead of recursively. 有时一次解压缩所有内容更容易,而不是递归。 If you simply want a parameter pack for_each, you can use a variant of the braced-init-list expansion trick ( Live demo at Coliru ): 如果你只想要一个参数包for_each,你可以使用braced -init-list扩展技巧的变种( 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';
}

By using func<B... >(); 通过使用func<B... >(); you are implying that func is a function template, but your previously defined func() is not. 你暗示func是一个函数模板,但你之前定义的func()不是。

You need to define a func() template that accepts zero template arguments. 您需要定义一个接受模板参数的func()模板。 Here's a working example (on g++ 4.8.1): 这是一个工作示例(在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;
}

Try this: 试试这个:

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
}

Consider what the invocation of the recursive call func<B...>(); 考虑一下递归调用func<B...>();的调用func<B...>(); looks like when B... is empty. 看起来像B...是空的。 It's calling func<>(); 它调用func<>(); but the definition of your attempted base case func() is not a template function, ie. 但是您尝试的基本情况func()的定义不是模板函数,即。 you can't call it via func<>(); 你不能通过func<>();调用它func<>();

Since we don't have partial specialization for function templates yet, (hopefully it will be supported soon) one way to do it is to use a class template to do the partial specialization and use the function to simply delegate the work to the class template. 由于我们还没有对函数模板进行部分特化,(希望很快就会支持),一种方法是使用类模板进行部分特化并使用函数将工作简单地委托给类模板。

#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>();
}

Personally I think this solution is cleaner than other solutions such as tagged dispatching or SFINAE, despite the cruft around operator() s. 我个人认为这个解决方案比其他解决方案更清晰,例如标记调度或SFINAE,尽管围绕operator() s。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM