Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
zhangyachen opened this issue Nov 7, 2020 · 0 comments
Labels

Comments

@zhangyachen
Copy link
Owner

zhangyachen commented Nov 7, 2020

模板参数不一定非得是类型,它们还可以是普通的数值。我们仍然使用前面文章的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&

(完)

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

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant