c++模板

函数模板

两个不同类型参数自动推断返回类型

自动推断返回类型

template<typename T1, typename T2> //typename是比较新的写法,老版中也可以写成class
auto max (T1 a, T2 b)
{
return b < a ? a : b;
}

decltype(true ? T1() : T2())返回一个比较通用的类型,std::decay_t萃取函数则用于去掉类似const&的修饰符

#include <type_traits>
template<typename T1, typename T2, typename RT =
std::decay_t<decltype(true ? T1() : T2())>> 
RT max (T1 a, T2 b)
{
return b < a ? a : b;
}

函数模板的重载

模板解析过程将优先选择非模板函数,而不是从模板实例化出来的函数。但可以加入尖括号显式调用,例如::max<>(7, 42)
在重载模板的时候,要尽可能少地做改动。

类模板

template<typename T>
class Stack {
  private:
    std::vector<T> elems; // elements
  public:
    void push(T const& elem); // push element
    void pop(); // pop element
    T const& top() const; // return top element
    bool empty() const { // return whether the stack is empty
    return elems.empty();
  }
};

在将这个 Stack类型用于声明的时候,除非可以推断出模板参数的类型,否则就必须使用 Stack(Stack 后面必须跟着<T>)。
不过如果在类模板内部使用 Stack而不是 Stack<T>,表明这个内部类的模板参数类型和模板类的参数类型相同。
以下两段代码是等价的。

template<typename T>
class Stack { 
  …
  Stack (Stack const&); // copy constructor
  Stack& operator= (Stack const&); // assignment operator 
  …
};
template<typename T>
class Stack { 
  …
  Stack (Stack<T> const&); // copy constructor
  Stack<T>& operator= (Stack<T> const&); // assignment operator 
  …
};

模板函数和模板成员函数只有在被调用的时候才会实例化。
如果一个类模板有static 成员 ,对每一个用到这个类模板的类型,相应的静态成员也只会被实例化一次

部分地使用类模板 模板参数只需要提供那些会被用到的操作,并不需要要为模板参数提供所有被模板成员函数用到的操作。

友元 通过友元重载类模板的运算符

模板类的特例化 可以对类模板的某一个模板参数进行特化,对特定的某一种类型,我们可以进行特殊的处理。

类模板的类型推导

通过用 0 初始化这个 stack 时,模板参数 T 被推断为 int,这样就会实例化出一个 Stack

template<typename T>
class Stack {
  private:
    std::vector<T> elems; // elements
  public:
    Stack () = default;
    Stack (T const& elem) // initialize stack with one element   
    : elems({elem}) {
    }
  …
};
Stack intStack = 0; // Stack<int> deduced since C++17

类模板对字符串常量的推断

template<typename T>
class Stack {
  private:
    std::vector<T> elems; // elements
  public:
    Stack () = default;
    Stack (T const& elem) //  按值传递Stack (T elem)
    : elems({elem}) {
    }
  …
};
Stack intStack = 0; // Stack<int> deduced since C++17
Stack stringStack = "bottom";

使用字符串初始化stack模板类时,有必要将构造函数声明成按值传递参数的形式,不然模板类型会识别成类似char const[7]的形式。
按值传递时,参数类型会被萃取,模板类型为char const *
更好的方案是当传递一个字符串常量或者 C 类型的字符串时,应该用std::string实例化 Stack 模板类,添加以下语句:
Stack( char const*) -> Stack<std::string>;
需要注意的是,此时初始化stack是不能使用=的方式,必须使用{}的方式。

Stack stringStack{"bottom"}; //right
Stack stringStack = "bottom"; //error

非类型模板参数

非类型模板参数,通常它们只能是整形常量

template<int Val, typename T>
T addValue (T x)
{
  return x + Val;
}

template<typename T, std::size_t Maxsize>
class Stack {
  private:
    std::array<T, Maxsize> elems; // elements
  ...
}
posted @ 2023-03-11 19:46  chilkings  阅读(26)  评论(0编辑  收藏  举报