IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [C++] 变参模板

    dutor发表于 2013-11-23 18:26:42
    love 0

      上文书介绍了 C++11 中的右值引用及其应用:移动语义和完美转发。本文介绍另外一个应用广泛的特性,变参模板。变参模板允许模板使用个数可变的参数类型来声明模板,包括类模板和函数模板。变参模板的基本语法是这样的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    void print()
    {
      cout<<endl;
    }
     
    template <typename T, typename... Args>
    void print(const T &t, const Args&... args)
    {
      cout<<t<<" ";
      print(args...);
    }
    int
    main()
    {
      print(123, 3.14, "tair");
      return 0;
    }

      上面实现了一个简单的类型安全的变参打印函数。
      结合右值引用,变参模板在 STL 中应用广泛,例如 vector 中的 emplace 函数族(每个 STL 容器都提供了适当接口的 emplace* 函数),用来使用其参数在内部内存单元上直接构造对象,不但避免了不必要的内存拷贝,还可以省去临时对象的构造:

    1
    2
    3
    4
    5
    
    template <class... Args>
    void vector<T>::emplace_back (Args&&... args);
     
    std::vector<string> v;
    v.emplace_back(10, '*'); //~ new(&vec[size()])string(10, '*')

      v.emplace_back(10, ‘*’) 在内部内存上使用 placement new 操作符,直接调用 std::string(size_t n, char c) 来构造对象。
      变参模板的另一个应用案例就是 tuple 的实现:

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    
    template <typename... Rest> struct Tuple;
    template <> struct Tuple<> {};
     
    template <typename First, typename ... Rest>
    struct Tuple<First, Rest...> : public Tuple<Rest...>
    {
      Tuple() : value() {}
      Tuple(First &&first, Rest&&... rest)
        : value(std::forward<First>(first)),
          Tuple<Rest...>(std::forward<Rest>(rest)...)
      {
      }
      First value;
    };
     
    template <size_t N, typename TP> struct Tuple_Element;
     
    template <typename T, typename ... Rest>
    struct Tuple_Element<0, Tuple<T, Rest...>>
    {
      typedef T type;
      typedef Tuple<T, Rest...> TPType;
    };
     
    template <size_t N, typename T, typename ... Rest>
    struct Tuple_Element<N, Tuple<T, Rest...>>
    : public Tuple_Element<N - 1, Tuple<Rest...>>
    {
    };
     
    template <size_t N, typename ... Rest>
    typename Tuple_Element<N, Tuple<Rest...>>::type&
    get(Tuple<Rest...> &tp)
    {
      typedef typename Tuple_Element<N, Tuple<Rest...>>::TPType type;
      return ((type&)tp).value;
    }
     
    int
    main()
    {
      Tuple<int, string, double> tp(3, "2", 1.);
      cout<<get<0>(tp)<<endl;
      cout<<get<1>(tp)<<endl;
      cout<<get<2>(tp)<<endl;
      return 0;
    }


沪ICP备19023445号-2号
友情链接