传统的变参方法都是基于上古的VA_ARGS来实现的,c++11引入了变参模板,把编写变参方法的便利度提高了的一个前所未有的高度。re2这个库很好的诠释了C++里面即便没有变参模板,也能做便利的变参实现。
【背景】
1 2 3 4 5 6 |
static bool FullMatchN(const StringPiece& text, const RE2& re, const Arg* const args[], int argc); static const VariadicFunction2< bool, const StringPiece&, const RE2&, Arg, RE2::FullMatchN> FullMatch; RE2::FullMatch("ruby:1234", "(\\w+)", &s)); RE2::FullMatch("ruby:123456789123", "(\\w+):(\\d+)", &s, &i); |
FullMatch需要提取匹配到的所有子串,而正则表达式本身的灵活性决定了这里的参数(匹配到的子串)必然是变化的。
【RE2实现】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
template <typename Result, typename Param0, typename Param1, typename Arg, Result (*Func)(Param0, Param1, const Arg* const [], int count)> class VariadicFunction2 { public: Result operator()(Param0 p0, Param1 p1) const { return Func(p0, p1, 0, 0); } Result operator()(Param0 p0, Param1 p1, const Arg& a0) const { const Arg* const args[] = { &a0 }; return Func(p0, p1, args, 1); } ... Result operator()(Param0 p0, Param1 p1, const Arg& a0, const Arg& a1, const Arg& a2, const Arg& a3, const Arg& a4, const Arg& a5, const Arg& a6, const Arg& a7, const Arg& a8, const Arg& a9, const Arg& a10, const Arg& a11, const Arg& a12, const Arg& a13, const Arg& a14, const Arg& a15, const Arg& a16, const Arg& a17, const Arg& a18, const Arg& a19, const Arg& a20, const Arg& a21, const Arg& a22, const Arg& a23, const Arg& a24, const Arg& a25, const Arg& a26, const Arg& a27, const Arg& a28, const Arg& a29, const Arg& a30, const Arg& a31) const { const Arg* const args[] = { &a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11, &a12, &a13, &a14, &a15, &a16, &a17, &a18, &a19, &a20, &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29, &a30, &a31 }; return Func(p0, p1, args, 32); } }; |
【使用c++11变参模板的实现】
1 2 3 4 5 6 7 8 9 10 |
template <typename Result, typename Param0, typename Param1, typename Arg, Result (*Func)(Param0, Param1, const Arg* const [], int count)> class VariadicFunction2 { public: template<typename... Args> Result operator()(Param0 p0, Param1 p1, Args... arg) const { const Arg* const args[] = { arg... }; return Func(p0, p1, args, sizeof(arg...)); } }; |
RE2的变参实现通过整齐的重载operator()来实现,最大支持32个参数,因为只实现了32个重载。
而反观使用C++11的变参模板,则简化了很多代码,且没有参数32的限制。后者的便利性自然是极高的,但是在编译器的通用性上,前者更加通用。在没有C++11的情况下,google::re2又给出了实现变参的很好的一个例子。