• 【C/C++】C++11 Variadic Templates


    Variadic Templates

    1、function template:利用“参数个数逐一递减”的特性,实现递归函数调用

    template <typename T, typename... Types>
    void func(const T& firstArg, const Types&... args) {
        处理 firstArg
        func(args...);
    }

    例一、实现类似 python 3 的 print()

     1 void print() { cout << endl; }    // 边界条件,当args为0个时调用
     2 
     3 template <typename T, typename... Types>
     4 void print(const T& firstArg, const Types&... args) {  
     5     cout << firstArg << ' ';
     6     print(args...);
     7 }
     8 
     9 int main() {
    10     print(7.5, "hello", bitset<16>(377), 42);    // print "7.5 hello 0000000101111001 42"
    11     return 0;
    12 }

    如果同时存在函数

    template <typename... Types>
    void print(const Types&... args) {
        ...
    }

    void print(const T& firstArg, const Types&... args) 与 void print(const Types&... args) 可以共存,可以编译通过。

    但前者比较特化,后者比较泛化,共存时永远不会调用后者。

    例二、模拟 C <cstdio> 的 printf(),引自 stackoverflow

     1 void Printf(const char* s) {
     2     while (*s) {
     3         if (*s == '%' && *(++s) != '%')
     4             throw runtime_error("invalid format string: missing arguments.");
     5         cout << *s++; 
     6     }
     7 }
     8 
     9 template <typename T, typename... Types>
    10 void Printf(const char* s, const T& firstArg, const Types&... args) {
    11     while (*s) {
    12         if (*s == '%' && *(++s) != '%') {
    13             cout << firstArg;
    14             Printf(++s, args...);
    15             return;
    16         }
    17         cout << *s++;
    18     }
    19 }
    20 
    21 int main() {
    22     int* pi = new int;
    23     Printf("[%p] %s = %f
    ", pi, "This is pi", 3.1415926);    // print "[0x21fcc20] This is pi = 3.14159"
    24     return 0;
    25 }

    2、class template:利用“参数个数逐一递减”导致“参数类型也逐一递减”的特性,实现递归继承或递归复合

    例一、对 first 和 last(头尾元素)的特别处理(模板偏特化+递归)

     1 // 使用tuple index和max index打印元素
     2 template <int IDX, int MAX, typename... Args>
     3 struct print_tuple {
     4     static void print(ostream& os, const tuple<Args...>& args) {
     5         os << get<IDX>(args) << (IDX + 1 == MAX ? "" : ", ");
     6         print_tuple<IDX + 1, MAX, Args...>::print(os, args);
     7     }
     8 };
     9 
    10 // 递归结束的偏特化
    11 template <int MAX, typename... Args>
    12 struct print_tuple<MAX, MAX, Args...> {
    13     static void print(ostream&, const tuple<Args...>&) {}
    14 };
    15 
    16 // output operator for tuple 
    17 template <typename... Args>
    18 ostream& operator<<(ostream& os, const tuple<Args...>& args) {
    19     os << '[';
    20     // 需要知道tuple的元素index,用sizeof...(Args)获得元素个数
    21     print_tuple<0, sizeof...(Args), Args...>::print(os, args);
    22     return os << ']';
    23 }
    24 
    25 int main() {
    26     cout << make_tuple(7.5, string("hello"), bitset<16>(377), 42);    // print "[7.5, hello, 0000000101111001, 42]"
    27     return 0;
    28 }

    例二、C++STL 中 tuple 的实现(类的递归继承)

    template <typename... Values> class tuple;
    template <> class tuple<> { };
    
    template <typename Head, typename... Tail>
    class tuple<Head, Tail...> : private tuple <Tail...> {
        typedef tuple<Tail...> inherited;
    public:
        tuple() { }
        tuple(Head v, Tail... vtail) : m_head(v), inherited(vtail...) { }    // 调用base ctor
        ...
    protected:
        Head m_head;
    };

     

    例三、模拟 tuple(类的递归复合)

    template <typename... Values> class tup;
    template <> class tup<> { };
    
    template <typename Head, typename... Tail>
    class tup<Head, Tail...> {
        typedef tup<Tail...> composited;
    public:
        tup() { }
        tup(Head v, Tail... vtail) : m_head(v), m_tail(vtail...) { }    // 递归复合
        ...
    protected:
        Head m_head;
        composited m_tail;
    };

    只是这种实现 tuple 的方式内存消耗较大

  • 相关阅读:
    Event事件的兼容性
    学会使用Google代码搜索
    event.srcElement怎么取得tr的title值及怎么利用样式编辑blogs
    Mac下MyEclipse配置Tomcat的方法
    Mac 下配置Tomcat7
    myEclipse导入现成项目出现错误
    Android——padding/margin/layout_alignParentRight详解
    Mac系统下Eclipse安装前端开发各类插件
    MyEclipse导入现成项目后报Target runtime Apache Tomcat v6.0 is not defined. 错误的解决办法
    Mac下配置PHP+MySql环境
  • 原文地址:https://www.cnblogs.com/wayne793377164/p/9104862.html
Copyright © 2020-2023  润新知