不需要遞歸。這是簡單的:
#include <iostream>
#include <string>
#include <typeinfo>
class A {
public:
template<typename parser>
void foohelper() {
std::cout << "handled a " << typeid(parser).name() << std::endl;
// do work here
}
template <typename... parsers>
void foo() {
using expand = int[];
(void) expand { 0, (foohelper<parsers>(), 0)... };
}
};
int main() {
A a;
a.foo<int, int, double, std::string>();
}
輸出樣本:
handled a i
handled a i
handled a d
handled a NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
編輯:
爲響應不符合微軟的編譯器的要求,這裏是另一種不依賴於未施膠陣列上的版本:
#include <iostream>
#include <string>
#include <typeinfo>
class A {
public:
template<typename parser>
void foohelper() {
std::cout << "handled a " << typeid(parser).name() << std::endl;
// do work here
}
template <typename... parsers>
void foo() {
// c++ strictly does not allow 0-sized arrays.
// so here we add a NOP just in case parsers is an empty type list
using expand = int[1 + sizeof...(parsers)];
(void) expand {
(foohelper<void>(), 0),
(foohelper<parsers>(), 0)...
};
}
};
// implement the NOP operation. Note specialisation is outside class definition.
template<> void
A::foohelper<void>() {}
int main() {
A a;
a.foo<int, int, double, std::string>();
a.foo<>();
}
編輯2:
具有前綴,後綴和分析器間調用的更完整示例。寫了這麼多的代碼後,你可能會開始思考,「嘿!我可以在這裏實現一個完整的領域特定語言!」,你會是對的。
然而,比這更復雜的可能會讓你對你的同事產生永恆的仇恨,所以我會避免沿着這條路線走下去。
#include <iostream>
#include <string>
#include <typeinfo>
class A {
public:
template<typename parser>
void foohelper() {
std::cout << "handled a " << typeid(parser).name();
// do work here
}
void prepare()
{
std::cout << "starting parsers: ";
}
void separator()
{
std::cout << ", ";
}
void nothing()
{
}
void done() {
std::cout << " done!" << std::endl;
}
template <typename... parsers>
void foo() {
// c++ strictly does not allow 0-sized arrays.
// so here we add a NOP just in case parsers is an empty type list
bool between = false;
using expand = int[2 + sizeof...(parsers)];
(void) expand {
(prepare(), 0),
((between ? separator() : nothing()), between = true, foohelper<parsers>(), 0)...,
(done(), 0)
};
}
};
int main() {
A a;
a.foo<int, int, double, std::string>();
a.foo<>();
}
輸出樣本:
starting parsers: handled a i, handled a i, handled a d, handled a NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE done!
starting parsers: done!
你嘗試移動一般(非專業)'foo'聲明上述專業之一,而類定義後,將所有定義? – Petr