用元編程來判斷STL類型

来源:https://www.cnblogs.com/ChebyshevTST/archive/2023/12/09/17891215.html
-Advertisement-
Play Games

在此之前,先來回顧元編程當中的一個重要概念。 template<typename _Tp, _Tp __v> struct integral_constant { static constexpr _Tp value = __v; typedef _Tp value_type; typedef in ...


  在此之前,先來回顧元編程當中的一個重要概念。

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

  吃飯去了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原文地址: Android圖表開源庫調研及使用示例 - Stars-One的雜貨小窩 之前做的幾個項目都是需要實現圖表統計展示,於是做之前調研了下,做下記錄 概述 AAChartCore-Kotlin 基於webview,本質上還是使用js PhilJay/MPAndroidChart,老牌使用原生 ...
  • 根據不同的 type 屬性值,輸入欄位擁有很多種形式。輸入欄位可以是文本欄位、覆選框、掩碼後的文本控制項、單選按鈕、按鈕等等。input標簽:用來定義輸入控制項。這個標簽非常有用,它可以實現各種各樣的表單控制項效果。 ...
  • Vue Router 配置 在Vue2 router裡面增加 const router = new VueRouter({ mode: 'history', base: '/admin/', //這裡路徑寫你打包後的網址路徑 routes: [ // 這裡是你的路由配置 ], }); vue.con ...
  • 在學習 SpringBoot 之前,建議先具備 SpringMVC(控制層)、Spring(業務層)和 Mybatis(持久層)的相關知識 1.1、概述 1.1.1、Spring的缺點 Spring 框架雖然很出色,但是有一個明顯的缺點:配置文件過於繁瑣和複雜; 在單體項目中,因為配置文件只需要編寫 ...
  • C-05.排序和分頁 1.排序 1.1 排序規則 使用ORDER BY子句排序。 ASC(ascend):升序,從低到高。 DESC(descend):降序,從高到低。 ORDER BY子句在SELECT語句的末尾,但不是最後,最後是分頁子句。 1.2 單列排序 mysql> SELECT last ...
  • 以系統里的出金交易為例, 與銀行對賬不外乎做兩件事:①T+1日拉取銀行賬單,保存銀行賬單交易流水;②銀行賬單交易流水與本系統里的通道交易流水比對並記錄差異。 數據表設計 數據表表名comment主要欄位 銀行賬單批次表 bank_bill_batch 銀行賬單表,每銀行每天一條記錄 batchNo- ...
  • 在Qt框架中,`QString` 是一個強大而靈活的字元串容器,專為處理 `Unicode` 字元而設計。它提供了許多方便的方法來操作和處理字元串,使得在跨平臺開發中能夠輕鬆地進行文本操作。QString 是 Qt 開發中不可或缺的一部分,它的靈活性和強大的功能使其成為處理文本和字元串操作的理想選擇... ...
  • 介紹瞭如何集成JSP模板到Spring Boot項目中。通過引入JSP依賴、配置JSP視圖解析器以及指定JSP訪問目錄,實現了JSP的集成和訪問。以及展示了整合MyBatis框架的步驟。首先介紹了引入MyBatis相關依賴的過程,然後講解了@MapperScan註解的使用,用於掃描DAO介面所在包並... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...