考虑最古老的TagDispatch技术,此技术广泛用于STL标准库
#include <iostream> #include <string> #include <sstream> using namespace std; struct StringTag {}; struct NumericTag {}; struct Int64 { int64_t data_; using tag = NumericTag; }; struct Int32 { int data_; using tag = NumericTag; }; struct String { std::string data_; using tag = StringTag; }; template<class T> auto length(T a, NumericTag) { std::stringstream ss; ss << a.data_; std::cout << ss.str().length() << std::endl; } template<class T> auto length(T a, StringTag){ std::cout << a.data_.length() << std::endl; } template<class T> auto length(T a) { typedef typename T::tag TagType; return length(a, TagType{}); } int main() { Int64 kk; kk.data_ = 12345; length(kk); String ss; ss.data_ = "12345"; length(ss); return 0; }
现在用C++17重写,可以把三个分离的length函数,合并成一个。代码如下:
#include <iostream> #include <string> #include <sstream> using namespace std; struct StringTag {}; struct NumericTag {}; struct Int64 { int64_t data_; using tag = NumericTag; }; struct Int32 { int data_; using tag = NumericTag; }; struct String { std::string data_; using tag = StringTag; }; template<class T> auto length(T a) { using TagType = typename T::tag; if constexpr (is_same<TagType, NumericTag>::value) { std::stringstream ss; ss << a.data_; std::cout << ss.str().length() << std::endl; } else if (is_same<TagType, StringTag>::value) { std::cout << a.data_.length() << std::endl; } else { return 0; } } int main() { Int64 kk; kk.data_ = 12345; length(kk); String ss; ss.data_ = "12345"; length(ss); return 0; }
如果没有机会使用TagDispatch技术,那一定是因为遇到基本数据类型或是自己无法修改源代码的类型。例如:int,就不能获得int::Tag这种信息。
现在我们换到另一种经典的Trait(萃取)技术,也是STL时代就开始的技术。代码如下:
#include <iostream> #include <string> using namespace std; namespace study{ template <typename T> struct is_numeric { static const bool value = false; }; template <> struct is_numeric<int64_t> { static const bool value = true; }; template <> struct is_numeric<int> { static const bool value = true; }; } namespace study { template <typename T> struct is_string { static const bool value = false; }; template <> struct is_string< std::string > { static const bool value = true; }; } namespace study { template <class T> void length(T a, typename std::enable_if< study::is_numeric<T>::value, size_t>::type* dummy = 0) { std::stringstream ss; ss << a; std::cout << ss.str().length() << std::endl; } template <class T> void length(T a, typename std::enable_if< study::is_string<T>::value, size_t>::type* dummy = 0) { std::cout << a.length() << std::endl; } } int main() { int x = 10; using namespace study; length(x) ; std::string str = "12345"; length(str); return 1; }
可以使用C++17的技术,丢掉繁琐的enable_if之类稀奇古怪的语法:
namespace study { template <class T> void length(T a) { if constexpr ( is_numeric<T>::value ) { std::stringstream ss; ss << a; std::cout << ss.str().length() << std::endl; } else if ( is_string<T>::value ) { std::cout << a.length() << std::endl; } } }
考虑模板的递归遍历算法,以一个简单的typelist为例,让编译器计算出类型列表中,体积最大的类型。需要一个结束递归的终结器。
namespace study{ template<class X, class...Xs> struct typelist { static constexpr size_t max_size() { constexpr size_t rest_max_size = typelist<Xs...>::max_size(); constexpr size_t this_size = sizeof(X); return this_size > rest_max_size ? this_size : rest_max_size; } }; //结束递归的终结器 template<class X> struct typelist<X> { static constexpr size_t max_size() { return sizeof(X); } }; } int main() { int n = study::typelist<int,char,double>::max_size(); return 1; }
C++17的便利设施,可以把终结器写在一起:
namespace study { template<class X, class...Xs> struct typelist { static constexpr size_t max_size() { if constexpr(sizeof...(Xs)>0) { constexpr size_t rest_max_size = typelist<Xs...>::max_size(); constexpr size_t this_size = sizeof(X); return this_size > rest_max_size ? this_size : rest_max_size; } else { return sizeof(X); } } }; } int main() { int n = study::typelist<int,char,double>::max_size(); return 1; }
总结:if constexpr语法完善了模板元编程的程序路径选择。
原文链接: https://www.cnblogs.com/thomas76/p/8530760.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;
也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/397586
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!