C++代码片段(三)过滤可变模板参数中某些类型的变量
生活随笔
收集整理的這篇文章主要介紹了
C++代码片段(三)过滤可变模板参数中某些类型的变量
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
將可變模板參數(shù)列表中的某些類(lèi)型過(guò)濾掉,然后返回剩下數(shù)據(jù)的元組。用到了上一篇中的判斷可變模板參數(shù)中是否包含某一特定類(lèi)型的方法
#include <iostream> #include <tuple> #include <string> #include <vector> #include <list>template <typename T, typename... Args> struct contains : public std::false_type {};template <typename T, typename U, typename... Args> struct contains<T, U, Args...> :public std::conditional_t<std::is_same_v<T, U>, std::true_type, contains<T, Args...>> {};template <typename... FilterArgs> struct type_filter {static constexpr auto filter() { return std::tuple{}; }template <typename T, typename... Args>static constexpr auto filter(T&& t, Args&&... args) {using type = std::remove_reference_t<T>;if constexpr (contains<type, FilterArgs...>::value) {return filter(std::forward<Args>(args)...);}else {return std::tuple_cat(std::make_tuple(std::forward<T>(t)), filter(std::forward<Args>(args)...));}} };實(shí)現(xiàn)原理
相當(dāng)于依次遍歷可變模板參數(shù)列表中的數(shù)據(jù),每次遍歷時(shí)判斷數(shù)據(jù)的類(lèi)型是否是想要過(guò)濾掉的類(lèi)型(也就是判斷當(dāng)前類(lèi)型是否存在于過(guò)濾類(lèi)型中),如果是則丟棄當(dāng)前數(shù)據(jù)繼續(xù)遍歷,否則保留數(shù)據(jù)
沒(méi)有過(guò)濾掉的數(shù)據(jù)保存在元組中,采用std::tuple_cat方法將兩個(gè)std::tuple連接成一個(gè)
std::tuple<int, double> t1{ 10, 2.5 }; std::tuple<std::string> t2{ "abc" }; auto t = std::tuple_cat(t1, t2); // decltype(t) = std::tuple<int, double, std::string>需要注意的問(wèn)題
過(guò)濾函數(shù)filter的聲明為
template <typename T, typename... Args> static constexpr auto filter(T&& t, Args&&... args);接收的參數(shù)類(lèi)型是T&&,所以分成兩種情況討論(假設(shè)傳入的類(lèi)型是int)
- 傳入的t是左值引用類(lèi)型int&,則T會(huì)被推導(dǎo)成int&,由于引用疊加效果,int&&& => int&
- 傳入的t是右值引用類(lèi)型int&&,則T會(huì)被推導(dǎo)成int,不存在引用疊加效果,int&& => int&&
而在調(diào)用contains
if constexpr (std::is_same_v<int&, int>) {std::cout << "int& is same as int\n"; } else {std::cout << "int& is different from int\n"; }// 輸出:int& is different from int所以需要在調(diào)用contains之前去掉類(lèi)型T上面的引用屬性,使用標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)
std::remove_reference_t<T>測(cè)試程序
#include <iostream> #include <tuple> #include <string> #include <vector> #include <list>template <typename T, typename... Args> struct contains : public std::false_type {};template <typename T, typename U, typename... Args> struct contains<T, U, Args...> :public std::conditional_t<std::is_same_v<T, U>, std::true_type, contains<T, Args...>> {};template <typename... FilterArgs> struct type_filter {static constexpr auto filter() { return std::tuple{}; }template <typename T, typename... Args>static constexpr auto filter(T&& t, Args&&... args) {using type = std::remove_reference_t<T>;if constexpr (contains<type, FilterArgs...>::value) {return filter(std::forward<Args>(args)...);}else {return std::tuple_cat(std::make_tuple(std::forward<T>(t)), filter(std::forward<Args>(args)...));}} };template <typename Tuple, typename Func, std::size_t... Idx> void for_each(Tuple&& t, Func&& f, std::index_sequence<Idx...>) {(f(std::get<Idx>(t)), ...); }template <typename... Args> void filter_test(Args&&... args) {auto t = type_filter<int, std::list<std::string>, std::vector<int>>::filter(std::forward<Args>(args)...);for_each(t, [](auto& item) {std::cout << item << std::endl;}, std::make_index_sequence<std::tuple_size_v<decltype(t)>>{}); }int main() {// l被推導(dǎo)為左值引用std::list<std::string>&// n被推導(dǎo)為左值引用int&// 字面值常量"abc", 20, 2.5被推導(dǎo)為右值引用std::string&&, int&&, double&&// vector被推導(dǎo)為右值引用std::vector<int>&&std::list<std::string> l{ "abc", "def", "123" };int n = 10;filter_test(l, "abc", n, 20, 2.5, std::vector<int>{1, 2, 3});return 0; } 與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的C++代码片段(三)过滤可变模板参数中某些类型的变量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 解决无法将自己github上的代码clo
- 下一篇: C++代码片段(四)萃取模板类的模板参数