当时用模板定义一个函数时,有时函数的返回类型是和模板参数相关的,这时可以通过decltype获得返回类型。
  template<typename It>
  decltype(*beg) get_begin(It beg)
  {
  return *beg;
  }
  但是这样写是无法通过编译的,因为decltype进行类型推断时,beg还不存在。所以这时需要使用尾置返回类型。
  template<typename It>
  auto get_begin(It beg) -> decltype(*beg)
  {
  return *beg;
  }
  std::cout<<"test tail return type of template: ";
  std::vector<int> numbers = {1, 2, 3, 4, 5};
  std::cout<<"get_begin: "<<get_begin(numbers.begin())<<std::endl;
  std::cout<<"test tail return type of template done. ";
  不定长模板
  新标准中,可以定义一个不定长度的模板参数列表。这种形式,一般和递归结合使用。
  template<typename T>
  std::ostream &print_variadic(std::ostream &os, const T &t)
  {
  return os<<t<<std::endl;
  }
  template<typename T, typename... Args>
  std::ostream &print_variadic(std::ostream &os, const T &t, const Args&... rest)
  {
  os<<t<<"(remain size: "<<sizeof...(Args)<<"), ";
  return print_variadic(os, rest...);
  }
  std::cout<<"test variadic template: ";
  print_variadic(std::cout, 100, "s", 56.76, 101);
  std::cout<<"test variadic template done. ";
  第一次为print_variadic传入了4个需要打印的对象,则实例化第二个不定长模板函数,将100赋值给t,并将剩余的3个参数打包成rest。
  在内部递归中,将不断的将rest包中的第一个参数拿出来付给t,剩余参数打包进行下一次递归调用。
  后只剩一个参数时,两种形式的print_variadic都可以匹配,但是第一种没有模版参数包的版本更加特例化,因此将调用第一种形式的print_variadic,结束递归。
  总结
  · 提供了一个名为function的标准库类,可以用function来表示多个不同形式的函数调用,只要这些函数调用的参数类型和返回类型是一致的
  · 在新标准中,可以声明一个类的模板参数类型为类的友元。
  · 新标准中,可以使用using为模板声明别名。
  · 新标准中,可以像为函数提供默认参数一样,为模板参数提供默认值。
  · 部分模板函数返回值需要使用尾置返回类型。
  · 新标准中,可以定义一个不定长度的模板参数列表,将参数打包。这种形式,一般和递归结合使用。