c++11-17 模板核心知识(三)—— 非类型模板参数 Nontype Template Parameters

朋友们可以关注下我的公众号,获得最及时的更新:

或者关注我的知乎账号 : https://www.zhihu.com/people/zhangyachen


模板参数不一定非得是类型,它们还可以是普通的数值。我们仍然使用前面文章的Stack的例子。

类模板的非类型模板参数

声明:

template <typename T, std::size_t Maxsize> 
class Stack {
private:
  std::array<T, Maxsize> elems; // elements
  std::size_t numElems;         // current number of elements
public:
  Stack();                  // constructor
  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 numElems == 0;
  }
  std::size_t size() const { // return current number of elements
    return numElems;
  }
};

实现:

template <typename T, std::size_t Maxsize>
Stack<T, Maxsize>::Stack() : numElems(0)  {
  // nothing else to do
}

template <typename T, std::size_t Maxsize>
void Stack<T, Maxsize>::push(T const &elem) {
  assert(numElems < Maxsize);
  elems[numElems] = elem; 
  ++numElems;        
}

使用:

Stack<int,20> int20Stack;       // stack of up to 20 ints
Stack<int,40> int40Stack;       // stack of up to 40 ints
Stack<std::string,40> stringStack;     // stack of up to 40 strings 

这个很简单,就不细说了。

函数模板的非类型模板参数

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

std::transform(source.begin(), source.end(), dest.begin(), addValue<5, int>);

再比如标准库type_traits中的enable_ifconditional:

template <bool _Bp, class _If, class _Then>
    struct _LIBCPP_TEMPLATE_VIS conditional {typedef _If type;};

template <bool, class _Tp = void> struct _LIBCPP_TEMPLATE_VIS enable_if {};

限制

必须是下面的类型:

  • 整型常量/枚举
  • 指向对象/函数/成员变量的指针
  • 对象/函数的左值引用
  • std::nullptr_t

当传递指针或者引用时,指向的对象不能是字符串常量、临时变量、数据成 员以及其它子对象。

使用auto推断非类型模板参数

从c++17起,可以使用auto推断非类型模板参数:

template <auto value> void f() { }

f<10>();               // deduces int

如果没有auto,想将非类型模板参数的类型也当做模板参数,那么必须声明两个模板参数:

template <typename Type, Type value> constexpr Type TConstant = value;

constexpr auto const MySuperConst = TConstant<int, 100>;

从c++17开始,只需要一个auto即可:

template <auto value> constexpr auto TConstant = value;

constexpr auto const MySuperConst = TConstant <100>;

在auto推导的的情况下获取类型:

template<auto Val, typename T = decltype(Val)>
T foo();

或者:

template<auto Val> struct Value {
   using ArgType = decltype(Val);
};

template<decltype(auto) N>也是可以的,这里N会被推断成引用类型:

template<decltype(auto) N>
class C {
...
};
int i;
C<(i)> x;      // N is int&

(完)

朋友们可以关注下我的公众号,获得最及时的更新:

posted @ 2020-11-08 23:24  张雅宸  阅读(805)  评论(0编辑  收藏  举报