首页 > 编程语言 >用元编程来判断STL类型

用元编程来判断STL类型

时间:2023-12-09 17:34:41浏览次数:36  
标签:std struct STL 编程 value template 用元 type unordered

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

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';
}

  吃饭去了。

标签:std,struct,STL,编程,value,template,用元,type,unordered
From: https://www.cnblogs.com/ChebyshevTST/p/17891215.html

相关文章

  • 深入探究 Python 异步编程:利用 asyncio 和 aiohttp 构建高效并发应用
    在现代编程中,异步编程已成为处理高并发和IO密集型任务的重要方式。Python提供了强大的异步编程支持,包括asyncio库和aiohttp等框架。本文将深入探讨异步编程的概念,以及在Python中如何利用异步框架来实现高效的并发编程。1.异步编程概念异步编程允许程序在等待IO操作完成时......
  • 上机编程[目录树收缩显示]学习交流
    1.    题目今天学习2022-11-25专业级第二题。在一个目录树中(假设都是目录),过深的目录路径不容易展示,为了提升用户体验,需要对目录进行收缩展示,求收缩后某一深度的目录个数。如图所示,原目录树及收缩后示意:1.  root                   root2.  ......
  • 使用Java实现面向对象编程 第八章 File IO 总结笔记
    java里操作文件1.第一步一定是获得这个文件(获得的文件,你是无法解析获得里面的内容,约等于获得冰。你只能知道大小颜色等。外表能够获取信息.)。2.第二步获得这个文件将这个文件转换成流。然后从这个io流里读取数据io流里又分为字符流(专门处理文字)字节流(专门处理2进制等文件)3.......
  • MAC安装编程环境的一些事项
    jdk安装java默认安装在如下目录下(不同版本不同目录)/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home环境变量配置sudochmodo+w/etc/profilevi /etc/profile加入下面内容JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home......
  • web服务器-socket编程
    客户端#include<stdio.h>#include<stdlib.h>#include<string.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<netinet/ip.h>#include<arpa/inet.h>#include<unistd.h>#inc......
  • 实验四 Web服务器1-socket编程
    一、代码#include<netinet/in.h>#include<arpa/inet.h>#include<netdb.h>#include<sys/types.h>#include<sys/socket.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<stdio.h>#de......
  • 实验四 Web服务器1-socket编程
    实验四Web服务器1-socket编程基于华为鲲鹏云服务器CentOS中(或Ubuntu),使用LinuxSocket实现:time服务器的客户端服务器,提交程序运行截图echo服务器的客户端服务器,提交程序运行截图,服务器把客户端传进来的内容加入“服务器进程pid你的学号姓名echo:”返回给客户端服务器部......
  • 2023-2024-1 20211327 实验四 Web服务器1-socket编程
    实验四Web服务器1-socket编程time服务器的客户端服务器time_server.c#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<arpa/inet.h>#include<sys/socket.h>#include<sys/types.h>#include<s......
  • Web服务器-socket编程
    代码#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<stdlib.h>#include<errno.h>#include<string.h>#include<netdb.h>#include<arpa/inet.h>#includ......
  • 关于STL的大整理
    set集合,用于去重和排序。用法set<储存的类型>容器名;常用函数//时间复杂度O(logn)insert()//插入元素,自动排序//示例s.insert(3);s.insert(1);s.insert(2);s.insert(4);s.insert(1);s.insert(5);//输出12345find()//查找一个数,返回迭代器count()//返回......