上文书介绍了 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;
}
Tags: .
你好!除了代码,此处没有多少原创之物,皆为本人搜集、整理、总结之记录与心得,欢迎转载分享!转载时请尽量注明出处,将不胜感激。祝你健康、快乐!
Home

Be the first to comment on this entry.

You must be logged in to post a comment.