美文网首页
第五章:模板的 tricky basics

第五章:模板的 tricky basics

作者: 找不到工作 | 来源:发表于2021-02-03 22:33 被阅读0次

本章会介绍一些模板的奇技淫巧。

5.1 用 typename 避免歧义

typename 可用于表示变量是一个类型。

template<typename T>
class MyClass {
  public:
  ...
  void foo() {
    typename T::SubType* ptr;
  }
};

这里,SubType 是在 T 类型里定义的。如果这里不用 typenameSubType 会被认为是某个非类型的数据(例如某个静态变量,或是枚举类),于是 T::SubType* ptr 就被当作了一个乘法。

结论是,当某个类型依赖于模板参数时必须用 typename 说明

例如,如下程序可以打印标准库容器的元素:

#include <iostream>


// print elements of an STL container

template<typename T>
void printcoll(T const& coll)
{
  for (typename T::const_iterator iter=coll.begin(); iter != coll.end(); iter++)
  {
    std::cout << *iter << " ";
  }
  std::cout << std::endl;
}

注意到我们使用了 typename 来指明 T::const_iterator 是一个类型。

5.2 零值初始化

对于基础类型如 int, double,没有默认构造函数来用默认值初始化,因此,对于以下模板:

template<typename T>
void foo()
{
  T x;  // x has undefined value is T is built-in type
}

对于基本类型,这个模板会初始化成未定义的值。自c++11开始,我们可以改进为:

template<typename T>
void foo()
{
  T x{};  // x has zero value is T is built-in type
}

5.3 使用 this

如果某个类继承自模板类,x 并不一定等于 this->x

#include <iostream>

template<typename T>
class Base {
public:
  void bar() {std::cout << "Base::bar is called" << std::endl;}
};

template<typename T>
class Derived : Base<T> {
public:
  void foo() {
    this->bar();  // if "this" is not used here, bar() can't be found
  }
};

结论:基类是模板类时,子类调用基类的方法需要使用 this->Base<T>::

5.4 template for raw arrays and string literals

略,不常用

5.5 类成员模板

5.5.1 使用 template 避免歧义

当调用模板类成员时,有时需要指明模板参数。这时候需要使用 template 关键字来确保第一个 < 不被当做“小于”处理。例如:

template<unsigned long N>
void printBitset(std::bitset<N> const& bs) {
  std::cout << bs.template to_string<char, std::char_traits<char>, std::allocator<char>>();
}

这里是调用了 std::bitset 中的模板类成员函数:

    template<class CharT = char,
             class Traits = char_Traits<CharT>,
             class Allocator = allocator<CharT>>
      basic_string<CharT, Traits, Allocator>
        to_string(CharT zero = CharT('0'), CharT one = CharT('1')) const;

如果这里不使用 template,编译器会认为 < 是“小于”符号。这个问题仅在它前面的变量依赖于模板参数时存在。例如,这里 ts 变量就是依赖于模板参数 N

结论:template 关键字仅在模板中使用,且仅在调用依赖模板参数的方法时使用

5.5.2 Generic Lambdas

c++14 引入了 generic lambdas,可以作为成员模板的简化。例如以下例子可以计算任意类型的和:

// c++14 or above
auto lambda_sum = [](auto x, auto y) {return x + y;};

它是以下例子的简化:

class MySum {
public:
  template<typename T1, typename T2>
  auto operator() (T1 x, T2 y) const {
    return x + y;
  }
};

相关文章

网友评论

      本文标题:第五章:模板的 tricky basics

      本文链接:https://www.haomeiwen.com/subject/rshzaktx.html