在此之前,先来回顾元编程当中的一个重要概念。

template<typename _Tp, _Tp __v>
struct integral_constant
{
static constexpr _Tp value = __v;
typedef _Tp value_type;
typedef integral_constant<_Tp, __v> type;
constexpr operator value_type() const noexcept { return value; }
#if __cplusplus > 201103L #define __cpp_lib_integral_constant_callable 201304L constexpr value_type operator()() const noexcept { return value; }
#endif
}; /// The type used as a compile-time boolean with true value.
using true_type = integral_constant<bool, true>; /// The type used as a compile-time boolean with false value.
using false_type = integral_constant<bool, false>;

  std::true_type和std::false_type其实就是std::integral_constant传入模板特定参数的情形,注意到integral_constant结构体当中的value_type,顾名思义指的是值的类型,对应到std::true_type和std::false_type就是true和false。

  先尝试着来写一个对std::vector的判断。

// vector
template <typename _Tp>
struct is_vector : std::false_type{}; template <typename _Tp>
struct is_vector<std::vector<_Tp>> : std::true_type{}; template <typename container_type>
bool is_vector_v = is_vector<container_type>::value; int main() {
std::vector<int> v1;
std::vector<double> v2;
std::vector<std::queue<int>> v3; std::cout << is_vector_v<decltype(v1)> << '\n';
std::cout << is_vector_v<decltype(v2)> << '\n';
std::cout << is_vector_v<decltype(v3)> << "\n\n"; std::queue<int> q1;
std::queue<double> q2;
std::queue<std::vector<int>> q3; std::cout << is_vector_v<decltype(q1)> << '\n';
std::cout << is_vector_v<decltype(q2)> << '\n';
std::cout << is_vector_v<decltype(q3)> << '\n';
}

  到这里还比较容易,用上面所讲到的std::true_type对is_vector模板类进行特化。拓展到全体STL容器类型,我们可以往此方向进行延申,对其它STL容器反复操作。

// vector
template <typename _Tp>
struct is_vector : std::false_type{}; template <typename _Tp>
struct is_vector<std::vector<_Tp>> : std::true_type{}; template <typename container_type>
bool is_vector_v = is_vector<container_type>::value; // queue
template <typename _Tp>
struct is_queue : std::false_type{}; template <typename _Tp>
struct is_queue<std::queue<_Tp>> : std::true_type{}; template <typename container_type>
bool is_queue_v = is_queue<container_type>::value; // string
template <typename _Tp>
struct is_string : std::false_type{}; template <>
struct is_string<std::string> : std::true_type{}; template <typename container_type>
bool is_string_v = is_string<container_type>::value; // array
template <typename _Tp>
struct is_array : std::false_type{}; template <typename _Tp, std::size_t N>
struct is_array<std::array<_Tp, N>> : std::true_type{}; template <typename container_type>
bool is_array_v = is_array<container_type>::value; // priority_queue
template <typename _Tp>
struct is_priority_queue : std::false_type{}; template <typename _Tp>
struct is_priority_queue<std::priority_queue<_Tp>> : std::true_type{}; template <typename container_type>
bool is_priority_queue_v = is_priority_queue<container_type>::value; // map
template <typename _Tp>
struct is_map : std::false_type{}; template <typename _Tp, typename _Up>
struct is_map<std::map<_Tp, _Up>> : std::true_type{}; template <typename container_type>
bool is_map_v = is_map<container_type>::value; // unordered_map
template <typename _Tp>
struct is_unordered_map : std::false_type{}; template <typename _Tp, typename _Up>
struct is_unordered_map<std::unordered_map<_Tp, _Up>> : std::true_type{}; template <typename container_type>
bool is_unordered_map_v = is_unordered_map<container_type>::value; // multimap
template <typename _Tp>
struct is_multimap : std::false_type{}; template <typename _Tp, typename _Up>
struct is_multimap<std::multimap<_Tp, _Up>> : std::true_type{}; template <typename container_type>
bool is_multimap_v = is_multimap<container_type>::value; // unordered_multimap
template <typename _Tp>
struct is_unordered_multimap : std::false_type{}; template <typename _Tp, typename _Up>
struct is_unordered_multimap<std::unordered_multimap<_Tp, _Up>> : std::true_type{}; template <typename container_type>
bool is_unordered_multimap_v = is_unordered_multimap<container_type>::value; // set
template <typename _Tp>
struct is_set : std::false_type{}; template <typename _Tp>
struct is_set<std::set<_Tp>> : std::true_type{}; template <typename container_type>
bool is_set_v = is_set<container_type>::value; // unordered_set
template <typename _Tp>
struct is_unordered_set : std::false_type{}; template <typename _Tp>
struct is_unordered_set<std::unordered_set<_Tp>> : std::true_type{}; template <typename container_type>
bool is_unordered_set_v = is_unordered_set<container_type>::value; // multiset
template <typename _Tp>
struct is_multiset : std::false_type{}; template <typename _Tp>
struct is_multiset<std::multiset<_Tp>> : std::true_type{}; template <typename container_type>
bool is_multiset_v = is_multiset<container_type>::value; // unordered_multiset
template <typename _Tp>
struct is_unordered_multiset : std::false_type{}; template <typename _Tp>
struct is_unordered_multiset<std::unordered_multiset<_Tp>> : std::true_type{}; template <typename container_type>
bool is_unordered_multiset_v = is_unordered_multiset<container_type>::value; // list
template <typename _Tp>
struct is_list : std::false_type{}; template <typename _Tp>
struct is_list<std::list<_Tp>> : std::true_type{}; template <typename container_type>
bool is_list_v = is_list<container_type>::value; // forward_list
template <typename _Tp>
struct is_forward_list : std::false_type{}; template <typename _Tp>
struct is_forward_list<std::forward_list<_Tp>> : std::true_type{}; template <typename container_type>
bool is_forward_list_v = is_forward_list<container_type>::value; // stack
template <typename _Tp>
struct is_stack : std::false_type{}; template <typename _Tp>
struct is_stack<std::stack<_Tp>> : std::true_type{}; template <typename container_type>
bool is_stack_v = is_stack<container_type>::value; // deque
template <typename _Tp>
struct is_deque : std::false_type{}; template <typename _Tp>
struct is_deque<std::deque<_Tp>> : std::true_type{}; template <typename container_type>
bool is_deque_v = is_deque<container_type>::value;

  (可能会有遗漏,我对STL的理解就是上面这些)好,接下来可以定义对STL类型判断的bool变量了。

// STL
template <typename _Tp>
bool is_stl_v = is_vector_v<_Tp> ||
is_array_v<_Tp> ||
is_queue_v<_Tp> ||
is_deque_v<_Tp> ||
is_set_v<_Tp> ||
is_unordered_set_v<_Tp> ||
is_multiset_v<_Tp> ||
is_unordered_multiset_v<_Tp> ||
is_map_v<_Tp> ||
is_unordered_map_v<_Tp> ||
is_multimap_v<_Tp> ||
is_unordered_multimap_v<_Tp> ||
is_stack_v<_Tp> ||
is_string_v<_Tp> ||
is_priority_queue_v<_Tp> ||
is_list_v<_Tp> ||
is_forward_list_v<_Tp>;

  接下来测试一下(其实不难理解,就是写起来比较费劲)。

#include <iostream>
#include <vector>
#include <queue>
#include <type_traits>
#include <string>
#include <array>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <list>
#include <forward_list>
#include <stack>
#include <deque> // vector
template <typename _Tp>
struct is_vector : std::false_type{}; template <typename _Tp>
struct is_vector<std::vector<_Tp>> : std::true_type{}; template <typename container_type>
bool is_vector_v = is_vector<container_type>::value; // queue
template <typename _Tp>
struct is_queue : std::false_type{}; template <typename _Tp>
struct is_queue<std::queue<_Tp>> : std::true_type{}; template <typename container_type>
bool is_queue_v = is_queue<container_type>::value; // string
template <typename _Tp>
struct is_string : std::false_type{}; template <>
struct is_string<std::string> : std::true_type{}; template <typename container_type>
bool is_string_v = is_string<container_type>::value; // array
template <typename _Tp>
struct is_array : std::false_type{}; template <typename _Tp, std::size_t N>
struct is_array<std::array<_Tp, N>> : std::true_type{}; template <typename container_type>
bool is_array_v = is_array<container_type>::value; // priority_queue
template <typename _Tp>
struct is_priority_queue : std::false_type{}; template <typename _Tp>
struct is_priority_queue<std::priority_queue<_Tp>> : std::true_type{}; template <typename container_type>
bool is_priority_queue_v = is_priority_queue<container_type>::value; // map
template <typename _Tp>
struct is_map : std::false_type{}; template <typename _Tp, typename _Up>
struct is_map<std::map<_Tp, _Up>> : std::true_type{}; template <typename container_type>
bool is_map_v = is_map<container_type>::value; // unordered_map
template <typename _Tp>
struct is_unordered_map : std::false_type{}; template <typename _Tp, typename _Up>
struct is_unordered_map<std::unordered_map<_Tp, _Up>> : std::true_type{}; template <typename container_type>
bool is_unordered_map_v = is_unordered_map<container_type>::value; // multimap
template <typename _Tp>
struct is_multimap : std::false_type{}; template <typename _Tp, typename _Up>
struct is_multimap<std::multimap<_Tp, _Up>> : std::true_type{}; template <typename container_type>
bool is_multimap_v = is_multimap<container_type>::value; // unordered_multimap
template <typename _Tp>
struct is_unordered_multimap : std::false_type{}; template <typename _Tp, typename _Up>
struct is_unordered_multimap<std::unordered_multimap<_Tp, _Up>> : std::true_type{}; template <typename container_type>
bool is_unordered_multimap_v = is_unordered_multimap<container_type>::value; // set
template <typename _Tp>
struct is_set : std::false_type{}; template <typename _Tp>
struct is_set<std::set<_Tp>> : std::true_type{}; template <typename container_type>
bool is_set_v = is_set<container_type>::value; // unordered_set
template <typename _Tp>
struct is_unordered_set : std::false_type{}; template <typename _Tp>
struct is_unordered_set<std::unordered_set<_Tp>> : std::true_type{}; template <typename container_type>
bool is_unordered_set_v = is_unordered_set<container_type>::value; // multiset
template <typename _Tp>
struct is_multiset : std::false_type{}; template <typename _Tp>
struct is_multiset<std::multiset<_Tp>> : std::true_type{}; template <typename container_type>
bool is_multiset_v = is_multiset<container_type>::value; // unordered_multiset
template <typename _Tp>
struct is_unordered_multiset : std::false_type{}; template <typename _Tp>
struct is_unordered_multiset<std::unordered_multiset<_Tp>> : std::true_type{}; template <typename container_type>
bool is_unordered_multiset_v = is_unordered_multiset<container_type>::value; // list
template <typename _Tp>
struct is_list : std::false_type{}; template <typename _Tp>
struct is_list<std::list<_Tp>> : std::true_type{}; template <typename container_type>
bool is_list_v = is_list<container_type>::value; // forward_list
template <typename _Tp>
struct is_forward_list : std::false_type{}; template <typename _Tp>
struct is_forward_list<std::forward_list<_Tp>> : std::true_type{}; template <typename container_type>
bool is_forward_list_v = is_forward_list<container_type>::value; // stack
template <typename _Tp>
struct is_stack : std::false_type{}; template <typename _Tp>
struct is_stack<std::stack<_Tp>> : std::true_type{}; template <typename container_type>
bool is_stack_v = is_stack<container_type>::value; // deque
template <typename _Tp>
struct is_deque : std::false_type{}; template <typename _Tp>
struct is_deque<std::deque<_Tp>> : std::true_type{}; template <typename container_type>
bool is_deque_v = is_deque<container_type>::value; // STL
template <typename _Tp>
bool is_stl_v = is_vector_v<_Tp> ||
is_array_v<_Tp> ||
is_queue_v<_Tp> ||
is_deque_v<_Tp> ||
is_set_v<_Tp> ||
is_unordered_set_v<_Tp> ||
is_multiset_v<_Tp> ||
is_unordered_multiset_v<_Tp> ||
is_map_v<_Tp> ||
is_unordered_map_v<_Tp> ||
is_multimap_v<_Tp> ||
is_unordered_multimap_v<_Tp> ||
is_stack_v<_Tp> ||
is_string_v<_Tp> ||
is_priority_queue_v<_Tp> ||
is_list_v<_Tp> ||
is_forward_list_v<_Tp>; struct Node {
int a;
int b;
}; int main() {
std::cout << std::boolalpha;
std::cout << is_stl_v<std::vector<int>> << '\n';
std::cout << is_stl_v<std::queue<int>> << '\n';
std::cout << is_stl_v<std::deque<int>> << '\n';
std::cout << is_stl_v<std::list<int>> << '\n';
std::cout << is_stl_v<std::forward_list<int>> << '\n';
std::cout << is_stl_v<std::array<int, 3>> << '\n';
std::cout << is_stl_v<std::priority_queue<int>> << '\n';
std::cout << is_stl_v<std::stack<int>> << '\n';
std::cout << is_stl_v<std::map<int, int>> << '\n';
std::cout << is_stl_v<std::unordered_map<int, int>> << '\n';
std::cout << is_stl_v<std::multimap<int, int>> << '\n';
std::cout << is_stl_v<std::unordered_multimap<int, int>> << '\n';
std::cout << is_stl_v<std::set<int>> << '\n';
std::cout << is_stl_v<std::unordered_set<int>> << '\n';
std::cout << is_stl_v<std::multiset<int>> << '\n';
std::cout << is_stl_v<std::unordered_multiset<int>> << '\n';
std::cout << is_stl_v<std::string> << '\n';
std::cout << is_stl_v<int> << '\n';
std::cout << is_stl_v<Node> << '\n';
}

  吃饭去了。

用元编程来判断STL类型的更多相关文章

  1. C++模板元编程(C++ template metaprogramming)

    实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...

  2. C++ 元编程 —— 让编译器帮你写程序

    目录 1 C++ 中的元编程 1.1 什么是元编程 1.2 元编程在 C++ 中的位置 1.3 C++ 元编程的历史 2 元编程的语言支持 2.1 C++ 中的模板类型 2.2 C++ 中的模板参数 ...

  3. C++ 模板元编程 学习笔记

    https://blog.csdn.net/K346K346/article/details/82748163 https://www.jianshu.com/p/b56d59f77d53 https ...

  4. c++ 模板元编程的一点体会

    趁着国庆长假快速翻了一遍传说中的.大名鼎鼎的 modern c++ design,钛合金狗眼顿时不保,已深深被其中各种模板奇技淫巧伤了身...论语言方面的深度,我看过的 c++ 书里大概只有 insi ...

  5. 《Effective C++》:条款48:理解力template 元编程

    Template metaprogramming(TMP,模板元编程)这是写template-based C++规划.编译过程.template metaprogramming随着C++写模板程序,化 ...

  6. effective c++ Item 48 了解模板元编程

    1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...

  7. 读书笔记 effective c++ Item 48 了解模板元编程

    1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...

  8. 初识C++模板元编程(Template Mega Programming)

    前言:毕设时在开源库上做的程序,但是源码看得很晕(当时导师告诉我这是模板元编程,可以不用太在乎),最近自己造轮子时想学习STL的源码,但也是一样的感觉,大致了解他这么做要干什么,但是不知道里面的机制. ...

  9. 现代c++与模板元编程

    最近在重温<c++程序设计新思维>这本经典著作,感慨颇多.由于成书较早,书中很多元编程的例子使用c++98实现的.而如今c++20即将带着concept,Ranges等新特性一同到来,不得 ...

  10. C++模板元编程----选择排序

    目录 目录 前言 代码详解 数据的结构 数据的操作 分割向量 合并向量 寻找最大值 排序 总结 前言 模板在C++一直是比较神秘的存在.STL和Boost中都有大量运用模板,但是对于普通的程序员来说, ...

随机推荐

  1. 微信小程序上传文件操作示范

    社会实践心得体会格式要求 提交的心得体会应为word文档,且图文并茂,全文段前.段后0,1.5倍行距. 题目:自拟,方正小标宋简体,小二号,加粗,居中. 个人信息:题目下方,宋体,小四号,加粗,居中, ...

  2. TDD、BDD、ATDD都是什么、有什么区别?(上)

    软件开发是一个迭代过程,包括编写.测试和改进代码,直到满足需求.测试驱动开发(TDD).行为驱动开发(BDD)和验收测试驱动开发(ATDD)是支持该过程的三种方法.TDD.BDD和ATDD都是软件开发 ...

  3. 纯前端导出word手写复杂表格,并还原成word。百分百还原表格。一文搞定前端表格导出为word

    本次的需求是手写一个养老院老人生活能力评定表,并且要能够录入信息,最终导出 表格因为有七页所以代码很多,可以不用看表格模板的详细代码. 先贴上最终效果图 填写完导出之后 基本上实现了样式的百分百还原导 ...

  4. c++中的宏#define用途

    宏的一些作用,包括但不限于这些 定义一个变量.字符串.类型 定义一个函数.条件表达式 条件编译.调试信息,异常类 定义结构体.命名空间 定义模版.枚举.函数对象 #define宏定义在C++中用于定义 ...

  5. SICTF-2023 #Round2-WP-Crypto | Misc

    Crypto 一.[签到]古典大杂烩 附件信息: 很明显可以看出来是base100,密码工具箱一把梭: SICTF{fe853b49-8730-462e-86f5-fc8e9789f077} 二.Ra ...

  6. Q-REG论文阅读

    Q-REG Jin, S., Barath, D., Pollefeys, M., & Armeni, I. (2023). Q-REG: End-to-End Trainable Point ...

  7. .NET 数据库大数据 方案(插入、更新、删除、查询 、插入或更新)

    1.功能介绍 (需要版本5.0.45) 海量数据操作ORM性能瓶颈在实体转换上面,并且不能使用常规的Sql去实现 当列越多转换越慢,SqlSugar将转换性能做到极致,并且采用数据库最佳API 操作数 ...

  8. Graph RAG: 知识图谱结合 LLM 的检索增强

    本文为大家揭示 NebulaGraph 率先提出的 Graph RAG 方法,这种结合知识图谱.图数据库作为大模型结合私有知识系统的最新技术栈,是 LLM+ 系列的第三篇,加上之前的图上下文学习.Te ...

  9. P8741 [蓝桥杯 2021 省 B] 填空问题 题解

    P8741 [蓝桥杯 2021 省 B] 填空问题 题解 题目传送门 欢迎大家指出错误并联系这个蒟蒻 更新日志 2023-05-09 23:19 文章完成 2023-05-09 23:20 通过审核 ...

  10. salesforce零基础学习(一百三十三)ListView的button思考

    本篇参考: salesforce零基础学习(九十五)lightning out salesforce零基础学习(一百一十)list button实现的一些有趣事情 https://help.sales ...