C++編譯期循環(huán)獲取變量類型詳情
一、問題
假設現(xiàn)在有一些屬性以及這些屬性對應的數(shù)值類型,比如:
"gender" --> char "age" --> int "height" --> float "IQ" ---> int "name" --> std::string "weight" --> double
在C++中,如何在編譯期依次循環(huán)獲取這些屬性的數(shù)值類型,并根據(jù)對應的數(shù)值類型做出相應的處理(屬性可能會增加)
二、解決方案
1.定義類型
首先把所有可能的類型用std::tuple列出:
using Types = std::tuple<float, int, double, std::string, char>; template<std::size_t N> using AttributeType = typename std::tuple_element<N, Types>::type;
這里,通過AttributeType<0>就可以得到float 類型
2.定義屬性集
將所有的屬性和其類型的對應關系列出,由于需要是編譯期獲得,必須類似加入constexpr 關鍵字:
constexpr const char* FLOAT_TYPE = "float"; constexpr const char* INT_TYPE = "int"; constexpr const char* DOUBLE_TYPE = "double"; constexpr const char* STRING_TYPE = "std::string"; constexpr const char* CHAR_TYPE = "float"; constexpr std::array<std::pair<const char*, const char*>, 6> attribute2type = {{ {"gender", CHAR_TYPE}, {"age", INT_TYPE}, {"height", FLOAT_TYPE}, {"IQ", INT_TYPE}, {"name", STRING_TYPE}, {"weight", DOUBLE_TYPE}, }};
3. 獲取類型索引
根據(jù)2中定義的類型字符串,獲取1中需要的類型索引N:
constexpr std::size_t getTypeIndex(const char* name) { return strings_equal(name, "float") ? 0: strings_equal(name, "int") ? 1: strings_equal(name, "double") ? 2: strings_equal(name, "std::string") ? 3: strings_equal(name, "char") ? 4: 5; // compilation error }
這里,需要一個編譯期進行字符串比較的函數(shù):
constexpr bool strings_equal(const char* a, const char* b) { return *a == *b && (*a == '\0' || strings_equal(a + 1, b + 1)); }
4. 編譯期循環(huán)
如何實現(xiàn)編譯期的類似for循環(huán)呢,顯然不能直接用for,模板的特性決定了可以使用編譯期遞歸來進行替代for循環(huán):
template <typename T> void print(const char* attribute) { std::cout << "attribute = " << attribute << ",type=" << typeid(T).name() << std::endl; } constexpr size_t LAST_INDEX = attribute2type.size() - 1; template <size_t T=LAST_INDEX> struct PrintHelper { public: PrintHelper() { doPrint<T>(); } private: template <size_t N> void doPrint() { print<AttributeType<getTypeIndex(std::get<N>(attribute2type).second)>>(std::get<N>(attribute2type).first); doPrint<N-1>(); } }; template <> template <> void PrintHelper<LAST_INDEX>::doPrint<0>() { print<AttributeType<getTypeIndex(std::get<0>(attribute2type).second)>>(std::get<0>(attribute2type).first); }
將上面所有的代碼放到一塊,就得到了一個可以在編譯期循環(huán)獲取變量類型的程序:
#include <string> #include <iostream> #include <typeinfo> #include <tuple> #include <array> using Types = std::tuple<float, int, double, std::string, char>; template<std::size_t N> using AttributeType = typename std::tuple_element<N, Types>::type; constexpr bool strings_equal(const char* a, const char* b) { return *a == *b && (*a == '\0' || strings_equal(a + 1, b + 1)); } constexpr std::size_t getTypeIndex(const char* name) { return strings_equal(name, "float") ? 0: strings_equal(name, "int") ? 1: strings_equal(name, "double") ? 2: strings_equal(name, "std::string") ? 3: strings_equal(name, "char") ? 4: 5; // compilation error } constexpr const char* FLOAT_TYPE = "float"; constexpr const char* INT_TYPE = "int"; constexpr const char* DOUBLE_TYPE = "double"; constexpr const char* STRING_TYPE = "std::string"; constexpr const char* CHAR_TYPE = "float"; constexpr std::array<std::pair<const char*, const char*>, 6> attribute2type = {{ {"gender", CHAR_TYPE}, {"age", INT_TYPE}, {"height", FLOAT_TYPE}, {"IQ", INT_TYPE}, {"name", STRING_TYPE}, {"weight", DOUBLE_TYPE}, }}; template <typename T> void print(const char* attribute) { std::cout << "attribute = " << attribute << ",type=" << typeid(T).name() << std::endl; } constexpr size_t LAST_INDEX = attribute2type.size() - 1; template <size_t T=LAST_INDEX> struct PrintHelper { public: PrintHelper() { doPrint<T>(); } private: template <size_t N> void doPrint() { print<AttributeType<getTypeIndex(std::get<N>(attribute2type).second)>>(std::get<N>(attribute2type).first); doPrint<N-1>(); } }; template <> template <> void PrintHelper<LAST_INDEX>::doPrint<0>() { print<AttributeType<getTypeIndex(std::get<0>(attribute2type).second)>>(std::get<0>(attribute2type).first); } int main() { PrintHelper<LAST_INDEX>(); return 0; }
上面程序輸出:
$ ./attributeWithType
attribute = weight,type=d
attribute = name,type=NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
attribute = IQ,type=i
attribute = height,type=f
attribute = age,type=i
attribute = gender,type=f
總結
本文通過下面幾個技術點實現(xiàn)了編譯期循環(huán)獲取變量類型:
- 通過std::tuple定義變量類型集合,
- 通過typename std::tuple_element<N, Types>::type獲取某個變量類型
- 通過編譯期遞歸實現(xiàn)編譯期字符串比較
- 通過std::get(attribute2type)獲取屬性編譯期遞歸實現(xiàn)循環(huán)獲取變量類型
到此這篇關于C++編譯期循環(huán)獲取變量類型詳情的文章就介紹到這了,更多相關C++循環(huán)獲取變量類型內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用MinGW使Windows通過gcc實現(xiàn)C或C++程序本地編譯執(zhí)行的方法
這篇文章主要介紹了使用MinGW使Windows通過gcc實現(xiàn)C或C++程序本地編譯執(zhí)行的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11排列和組合算法的實現(xiàn)方法_C語言經(jīng)典案例
下面小編就為大家?guī)硪黄帕泻徒M合算法的實現(xiàn)方法_C語言經(jīng)典案例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09