用元编程来判断STL类型

这篇具有很好参考价值的文章主要介绍了用元编程来判断STL类型。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

  吃饭去了。文章来源地址https://www.toymoban.com/news/detail-749976.html

到了这里,关于用元编程来判断STL类型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 〖程序员的自我修养 - 认知剖析篇②〗- 学习编程之前你需要知道这些

    人之所以会觉得迷茫,本质上是欠缺对自己的一个控制力、识别庞杂信息、去伪存真的独立思考与认知能力。 说明:该文属于 程序员的自我修养 专栏, 购买任意白宝书体系化专栏可加入 易编程社区, 早鸟价订阅模式除外 。 福利:加入社区的小伙伴们,除了可以获取博主

    2024年02月12日
    浏览(35)
  • JavaScript 类型判断及类型转换规则

    ✍创作者:全栈弄潮儿 🏡 个人主页: 全栈弄潮儿的个人主页 🏙️ 个人社区,欢迎你的加入:全栈弄潮儿的个人社区 📙 专栏地址,欢迎订阅:前端架构师之路 JavaScript 具有七种内置数据类型,它们分别是: null undefined boolean number string object symbol 其中,前面五种为基本类

    2024年01月19日
    浏览(33)
  • C++ 为什么double类型不能直接判断等于0 两个double类型怎么判断相等

    精度丢失, 十进制小数部分在转换成2进制的时候经常会出现无限位的二进制小数,计算机存储小数有长度限制,所以会进行截取部分小数进行存储,计算机只能存储大概的值,而不是精确的值 。 例如: 判断一个单精度浮点数:则是 if( abs(f) = 1e-6); 要判断一个双精度浮点数

    2024年02月12日
    浏览(45)
  • js数据类型和判断数据类型的方法

    js数据类型 1.基本数据类型(原始类型): number boolean string null:空对象 undefined:未定义 Symbol(es6新增): 表示独一无二的值。 为了解决对象实例新的方法与已有方法名冲突问题 。 每个从 Symbol() 返回的 symbol 值都是唯一的,从而确保每个属性的名字都是独一无二的。 Sym

    2024年02月07日
    浏览(35)
  • Java对象类型的转换+instanceOf判断对象类型

    将子类的实例对象定义为父类类型,这种称为 向上转型 ;将父类的实例对象定义为子类类型,这种称为 向下转型 ,向下转型必须使用 显示转换 ,否则编译器会报错。           instanceof操作符,可以用来判断是否一个类实现了某个接口,也可以用来判断一个实例对象是否

    2024年02月08日
    浏览(36)
  • 如何判断反馈电路的类型-反馈类型-三极管

    反馈电路类型很多,可根据不同的标准分类: ①根据反馈的极性分:有正反馈和负反馈。 ②根据反馈信号和输出信号的关系分:有电压反馈和电流反馈。 ③根据反馈信号和输入信号的关系分:有串联反馈和并联反馈。 ④根据反馈信号是交流或直流分:有交流反馈和直流反馈

    2024年02月12日
    浏览(45)
  • Matlab编程中常用到各种数学符号和特殊字符,如希腊字母、上下标、箭头符号等。在此,我们介绍如何在Matlab中快速输入这些符号,并提供相应的源代码示例。

    Matlab编程中常用到各种数学符号和特殊字符,如希腊字母、上下标、箭头符号等。在此,我们介绍如何在Matlab中快速输入这些符号,并提供相应的源代码示例。 希腊字母: Matlab中快速输入希腊字母,可以使用latex风格的命令。例如: alpha 输入alpha,即可输入希腊字母α beta

    2024年02月14日
    浏览(30)
  • java判断文件类型

    Java可以使用文件后缀名或文件头来判断文件类型。 使用文件后缀名判断: 首先使用File类获取文件名,例如:File file = new File(\\\"example.txt\\\"); 然后使用getName()方法获取文件名,例如:String fileName = file.getName(); 接着使用substring()方法截取文件后缀名,例如:String fileType = fileName.s

    2024年02月16日
    浏览(33)
  • 类型判断为空

    1 ★★★ 例1 : 判断集合是否为空: 2 CollectionUtils.isEmpty(null); //控制台打印:true 3 CollectionUtils.isEmpty(new ArrayList());//控制台打印:true 4 CollectionUtils.isEmpty({a,b});//控制台打印:false 5 6 ★★★ 例2: 判断集合是否不为空: 7 CollectionUtils.isNotEmpty(null); //控制台打印:false 8 CollectionUtils.i

    2024年02月09日
    浏览(25)
  • C++标准模板(STL)- 类型支持 (数值极限,C 数值极限接口)

    参阅 std::numeric_limits 接口 定义于头文件 cstdint PTRDIFF_MIN (C++11) std::ptrdiff_t 类型对象的最小值 (宏常量) PTRDIFF_MAX (C++11) std::ptrdiff_t 类型对象的最大值 (宏常量) SIZE_MAX (C++11) std::size_t 类型对象的最大值 (宏常量) SIG_ATOMIC_MIN (C++11) std::sig_atomic_t 类型对象的最小值 (宏常量) SIG_ATOMIC_

    2024年02月07日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包