zoukankan      html  css  js  c++  java
  • c++11-17 模板核心知识(三)—— 非类型模板参数 Nontype Template Parameters

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

    (完)

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

  • 相关阅读:
    ORACLE锁表问题
    迅雷极速版解决版本太旧提示问题
    迅雷极速版任务出错的解决办法(亲测可用)
    百度文库免积分免费下载工具的原理与实现
    C#启动另一个应用程序并传参数
    C#设置WebBrowser IE浏览器版本
    JS强制刷新页面、清除缓存刷新
    JS播放声音
    Chrome插件(扩展)开发全攻略
    IIS7.5全站301跳转,内页+带参数url,这才是真正的全站跳转
  • 原文地址:https://www.cnblogs.com/zhangyachen/p/13946444.html
Copyright © 2011-2022 走看看