隨著C++ 11的語法越來越復雜,功能也越來越強。用泛型+返回類型推導的方法來實現常量字符串的處理,能實現宏實現不了的地方,並且在編譯期實現
SO上的牛人太多了,以下是出處
http://stackoverflow.com/questions/15858141/conveniently-declaring-compile-time-strings-in-c/15890335#15890335
1.定義
1 namespace blog { 2 typedef long long hash64; 3 namespace const_expr 4 { 5 constexpr hash64 prime = 0x100000001B3ull; 6 constexpr hash64 basis = 0xCBF29CE484222325ull; 7 } 8 constexpr hash64 make_hash_static(char const* str) 9 { 10 return (*str) ? (*(str + 1)) ? (((*str) * const_expr::prime + const_expr::basis) ^ make_hash_static(str + 1)) : ((*str) * const_expr::prime + const_expr::basis) : 0; 11 } 12 13 constexpr hash64 operator "" _hash(char const* p, size_t) 14 { 15 return make_hash_static(p); 16 } 17 template<char>using charDummy = char; 18 template <int N> 19 constexpr char at(const char* a) { return a[N]; } 20 template<int... dummy> 21 struct F 22 { 23 const char Name[sizeof...(dummy)+1]; 24 const hash64 Hash; 25 const int Length; 26 const int Size; 27 28 constexpr F(const char* a) : Name{ at<dummy>(a)..., 0 }, Length(sizeof...(dummy)), Size(sizeof...(dummy)+1), Hash(a[0] * const_expr::prime + const_expr::basis){} 29 constexpr F(hash64 h, charDummy<dummy>... a) : Name{ a..., 0 }, Length(sizeof...(dummy)), Size(sizeof...(dummy)+1), Hash(h){} 30 constexpr F(const F& a) : Name{ a.Name[dummy]..., 0 }, Length(a.Length), Size(a.Size), Hash(a.Hash){} 31 32 template<int... dummyB> 33 constexpr F<dummy..., sizeof...(dummy)+dummyB...> operator + (F<dummyB...> b)const 34 { 35 return{ this->Hash ^ b.Hash,this->Name[dummy]..., b.Name[dummyB]... }; 36 } 37 operator const char*()const { return Name; } 38 }; 39 40 template<int I> 41 struct get_string 42 { 43 constexpr static auto g(const char* a) -> decltype(get_string<I - 1>::g(a) + F<0>(a + I)) 44 { 45 return get_string<I - 1>::g(a) + F<0>(a + I); 46 } 47 }; 48 49 template<> 50 struct get_string<0> 51 { 52 constexpr static F<0> g(const char* a) 53 { 54 return{ a }; 55 } 56 }; 57 58 template<int I> 59 constexpr auto str(const char(&a)[I]) -> decltype(get_string<I - 2>::g(a)) 60 { 61 return get_string<I - 2>::g(a); 62 } 63 }
2.使用
1 constexpr auto s = blog::str("abc")+ blog::str(blog_numb2str(12345678)) + blog::str("edf"); 2 std::cout << s.Name << std::endl; 3 std::cout << s.Hash << std::endl; 4 std::cout << s.Length << std::endl; 5 std::cout << s.Size << std::endl; 6 using namespace blog; 7 switch (s.Hash) { 8 case "abcedf"_hash: 9 std::cout << "s is " << s.Hash << std::endl; 10 break; 11 case s.Hash + 1: 12 break; 13 case "abc12345678edf"_hash: 14 std::cout << "s is " << s.Name << std::endl; 15 break; 16 }
3.結果
abc2345678edf
535462162733975
14
15
s is abc2345678edf
4.優缺點