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

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. 【路由器】OpenWrt 手动编译 ipk

    目录 .ipk 文件 编译准备 编译 .ipk 文件 更新 feeds 配置平台 获取交叉编译链 添加需要编译的第三方软件包 参考资料 .ipk 文件 .ipk 文件是可以通过 OpenWrt 的包管 ...

  2. 使用 Laf 一周内上线美术狮 AI 绘画小程序

    "美术狮 AI 绘画"(以下简称"美术狮"),是我们小团队的一次尝试,定位是人人都可以上手的,充满创意的,理解中文和中国文化的图片生成工具. 在完善图像模型和论 ...

  3. 【Azure Batch】在批处理的Task中如何让它执行多个CMD指令呢

    问题描述 根据Azure Batch的入门文档(使用 Azure 门户创建 Batch 帐户并运行作业 : https://docs.azure.cn/zh-cn/batch/quick-create ...

  4. 支持JDK19虚拟线程的web框架,之四:看源码,了解quarkus如何支持虚拟线程

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<支持JDK19虚拟线程的web ...

  5. 3 分钟把高质量 AI 知识库 FastGPT 装进企业微信

    FastGPT V4 已经上线,直接冲上 GitHub Trending. 如果你还不知道 FastGPT 是什么,可以先去看看作者的介绍 使用 FastGPT 构建高质量 AI 知识库 非常多的企业 ...

  6. Record - Stirling Number / FK. & SK.

    Part. 1 Stirling Number / FK. Def. 定义 \(\begin{bmatrix}n \\ m\end{bmatrix}\) 表示将 \(n\) 个元素分成 \(m\) 个 ...

  7. HTTPS相比HTTP为什么安全

    HTTPS(超文本传输协议[安全]) 1.HTTPS为什么叫安全的超文本传输协议 在HTTPS中,S是Security的意思,是安全的意思,而HTTP是超文本传输协议,这就不得不谈起HTTP在安全方面 ...

  8. Linux系列教程——Linux文件编辑、Linux用户管理

    @ 目录 1 Linux基本权限 1.权限基本概述 1.什么是权限? 2.为什么要有权限? 3.权限与用户之间的关系? 4.权限中的rwx分别代表什么含义? 2.权限设置示例 1.为什么要设定权限,我 ...

  9. linux日常运维(一)

    - 进程管理ps.top - 任务计划crontab 进程管理 概念:进程是在自身的虚拟地址空间运行的一个单独的程序. 进程和程序区别:程序只是一个静态的命令集合,不占系统的运行资源:而进程是一个随时 ...

  10. 中国科教工作者协会与CCF PTA联合认证学习须知

    中国科教工作者协会与CCF PTA联合认证学习须知 1.参与认证人员需在科技学堂(www.sciclass.cn)上进行课程学习,然后在PTA官网(pta.ccf.org.cn)报名并参加认证考试,考 ...