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_if
和conditional
:
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&
(完)
朋友们可以关注下我的公众号,获得最及时的更新:
c++11-17 模板核心知识(三)—— 非类型模板参数 Nontype Template Parameters的更多相关文章
- c++11-17 模板核心知识(十一)—— 编写泛型库需要的基本技术
Callables 函数对象 Function Objects 处理成员函数及额外的参数 std::invoke<>() 统一包装 泛型库的其他基本技术 Type Traits std:: ...
- c++11-17 模板核心知识(十二)—— 模板的模板参数 Template Template Parameters
概念 举例 模板的模板参数的参数匹配 Template Template Argument Matching 解决办法一 解决办法二 概念 一个模板的参数是模板类型. 举例 在c++11-17 模板核 ...
- c++11-17 模板核心知识(十四)—— 解析模板之依赖型模板名称(.template/->template/::template)
tokenization与parsing 解析模板之类型的依赖名称 Dependent Names of Templates Example One Example Two Example Three ...
- c++11-17 模板核心知识(十五)—— 解析模板之依赖型类型名称与typename Dependent Names of Types
模板名称的问题及解决 typename规则 C++20 typename 上篇文章c++11-17 模板核心知识(十四)-- 解析模板之依赖型模板名称 Dependent Names of Templ ...
- C++非类型模板参数
对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数.在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定.但是在这里,我们面对的是这 ...
- C++ Template之非类型模板参数
非类型模板参数是通过基本变量类型引入,例如int,在使用时必须显式自定值,不能通过推断. 非类型模板参数的限制:不能是浮点数(在vc6.0上测试可以为浮点型),对象以及指向内部链接对象的指针. #in ...
- C++标准库函数 end 的实现原理(非类型模板参数)
在刚开始学习<C++ Primer>的时候遇到了 end 函数,感觉很神奇,但又很迷惑:为什么能获得数组的尾后指针呢?编译器也不会在内存中申请一块空间放数组元素的个数啊!最近再一次遇到了 ...
- C++ Templates(1.3 多模板参数 Multiple Template Parameters)
返回完整目录 目录 1.3 多模板参数 Multiple Template Parameters 1.3.1 为返回类型设置模板参数参数 Template Parameters for Return ...
- c++11-17 模板核心知识(一)—— 函数模板
1.1 定义函数模板 1.2 使用函数模板 1.3 两阶段翻译 Two-Phase Translation 1.3.1 模板的编译和链接问题 1.4 多模板参数 1.4.1 引入额外模板参数作为返回值 ...
随机推荐
- C++中数组作为形参的方法
转载:https://blog.csdn.net/qq_33374294/article/details/90769668 原链接:https://www.cnblogs.com/abella/p/1 ...
- 【题解】[USACO09NOV]A Coin Game S
Link \(\text{Solution:}\) 菜鸡自己想出来了状态设计,但是没有实现出来--菜死了 设\(dp[i][j]\)表示该选第\(i\)个,最多选\(j\)个的最优解.注意这里的定义仅 ...
- Camera插件之CinematicCamera介绍
Camera插件之CinematicCamera 继承自PerspectiveCame 构造函数引用的PerspectiveCamera的构造函数, 代码如下 var CinematicCamera ...
- Java源码详解系列(十一)--Spring的使用和源码
Spring 是一个一站式的 Java 框架,致力于提高我们项目开发的效率.通过 Spring,我们可以避免编写大量额外代码,更专注于我们的核心逻辑.目前,Spring 已经成为最受欢迎的 Java ...
- springboot2.2.2企业级项目整合redis与redis 工具类大全
1.springboot2.2.2整合redis教程很多,为此编写了比较完整的redis工具类,符合企业级开发使用的工具类 2.springboot与redis maven相关的依赖 <depe ...
- MeteoInfoLab脚本示例:格点数据散点图
绘制格点数据的散点图,用scaterm函数. 脚本程序: f = addfile('D:/Temp/GrADS/model.ctl') ps = f['PS'][0,(10,60),(60,140)] ...
- c语言版去除源代码注释
去除代码中注释需要注意下面几点 首先注释有"/*"开始到"*/"结束的多行或单行注释 其次还有"//"这种单行注释 另外还需要注意双引号和单 ...
- Linux系统编程 —线程同步概念
同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...
- 习题3-5 谜题(Puzzle, ACM/ICPC World Finals 1993, UVa227)
#include<stdio.h> #include<string.h> char s[5][5]; int main() { while(gets(s[0])) { int ...
- 双栈排序(洛谷P1155)二分图的判定+思维贪心
题目:戳这里 题目大意: 给你一个数列,问能否通过两个栈的push与pop把它输出成一个升序序列(每个数只能入队并出队一次) 不能的话输出0,能的话输出操作方法 主要思路: 1.判断是否可以成功输出升 ...