c – 切换语句可变模板扩展

c – 切换语句可变模板扩展,第1张

概述让我考虑下列合成例子: inline int fun2(int x) { return x;}inline int fun2(double x) { return 0; }inline int fun2(float x) { return -1; }int fun(const std::tuple<int,double,float>& t, std:: 让我考虑下列合成例子:
inline int fun2(int x) {    return x;}inline int fun2(double x) {    return 0;   }inline int fun2(float x) {    return -1;   }int fun(const std::tuple<int,double,float>& t,std::size_t i) {    switch(i) {        case 0: return fun2(std::get<0>(t));        case 1: return fun2(std::get<1>(t));        case 2: return fun2(std::get<2>(t));    }    }

问题是我应该如何将其扩展到一般情况

template<class... Args> int fun(const std::tuple<Args...>& t,std::size_t i) {// ?}

保证

> fun2可以嵌入乐趣
>搜索复杂度不逊于O(log(i))(对于大i).

众所周知,当足够大的开关扩展时,优化器通常使用查找跳转表或编译时二叉搜索树.所以,我想保持这个属性影响大量项目的性能.

更新#3:我用均匀随机索引值重新测量了性能:

1       10      20      100@TartanLlama    gcc               ~0      42.9235 44.7900 46.5233    clang             10.2046 38.7656 40.4316 41.7557@chris-beck    gcc               ~0      37.564  51.3653 81.552    clang             ~0      38.0361 51.6968 83.7704naive tail recursion    gcc                3.0798 40.6061 48.6744 118.171    clang             11.5907 40.6197 42.8172 137.066manual switch statement    gcc                       41.7236     clang                      7.3768

更新#2:似乎clang能够在@TartanLlama解决方案中内联函数,而gcc总是生成函数调用.

解决方法 好的,我重写了我的答案.这给了什么TartanLlama和我之前建议的不同的方法.这符合您的复杂性要求,并且不使用函数指针,因此一切都是可以联机的.

编辑:非常感谢Yakk指出一个非常显着的优化(对于编译时模板递归深度需要)在注释中

基本上,我使用模板来形成类型/函数处理程序的二叉树,并手动实现二进制搜索.

可能使用mpl或boost :: fusion来更干净地执行此 *** 作,但是这个实现是自包含的.

它绝对符合您的要求,即函数是可以并行的,并且运行时查询在元组中的类型数量是O(log n).

这是完整的列表:

#include <cassert>#include <cstdint>#include <tuple>#include <iostream>using std::size_t;// Basic typeList objecttemplate<typename... TL>struct TypeList{   static const int size = sizeof...(TL);};// Metafunction Concat: Concatenate two typeListstemplate<typename L,typename R>struct Concat;template<typename... TL,typename... TR>struct Concat <TypeList<TL...>,TypeList<TR...>> {    typedef TypeList<TL...,TR...> type;};template<typename L,typename R>using Concat_t = typename Concat<L,R>::type;// Metafunction First: Get first type from a typeListtemplate<typename T>struct First;template<typename T,typename... TL>struct First <TypeList<T,TL...>> {    typedef T type;};template<typename T>using First_t = typename First<T>::type;// Metafunction Split: Split a typeList at a particular indextemplate<int i,typename TL>struct Split;template<int k,typename... TL>struct Split<k,TypeList<TL...>> {private:    typedef Split<k/2,TypeList<TL...>> FirstSplit;    typedef Split<k-k/2,typename FirstSplit::R> SecondSplit;public:    typedef Concat_t<typename FirstSplit::L,typename SecondSplit::L> L;    typedef typename SecondSplit::R R;};template<typename T,typename... TL>struct Split<0,TypeList<T,TL...>> {    typedef TypeList<> L;    typedef TypeList<T,TL...> R;};template<typename T,typename... TL>struct Split<1,TL...>> {    typedef TypeList<T> L;    typedef TypeList<TL...> R;};template<int k>struct Split<k,TypeList<>> {    typedef TypeList<> L;    typedef TypeList<> R;};// Metafunction SubdivIDe: Split a typeList into two roughly equal typeListstemplate<typename TL>struct SubdivIDe : Split<TL::size / 2,TL> {};// Metafunction MakeTree: Make a tree from a typeListtemplate<typename T>struct MakeTree;/*template<>struct MakeTree<TypeList<>> {    typedef TypeList<> L;    typedef TypeList<> R;    static const int size = 0;};*/template<typename T>struct MakeTree<TypeList<T>> {    typedef TypeList<> L;    typedef TypeList<T> R;    static const int size = R::size;};template<typename T1,typename T2,typename... TL>struct MakeTree<TypeList<T1,T2,TL...>> {private:    typedef TypeList<T1,TL...> MyList;    typedef SubdivIDe<MyList> MySubdivIDe;public:    typedef MakeTree<typename MySubdivIDe::L> L;    typedef MakeTree<typename MySubdivIDe::R> R;    static const int size = L::size + R::size;};// Typehandler: What our Lists will be made oftemplate<typename T>struct type_handler_helper {    typedef int result_type;    typedef T input_type;    typedef result_type (*func_ptr_type)(const input_type &);};template<typename T,typename type_handler_helper<T>::func_ptr_type me>struct type_handler {    typedef type_handler_helper<T> base;    typedef typename base::func_ptr_type func_ptr_type;    typedef typename base::result_type result_type;    typedef typename base::input_type input_type;    static constexpr func_ptr_type my_func = me;    static result_type apply(const input_type & t) {        return me(t);    }};// Binary search implementationtemplate <typename T,bool b = (T::L::size != 0)>struct apply_helper;template <typename T>struct apply_helper<T,false> {    template<typename V>    static int apply(const V & v,size_t index) {        assert(index == 0);        return First_t<typename T::R>::apply(v);    }};template <typename T>struct apply_helper<T,true> {    template<typename V>    static int apply(const V & v,size_t index) {        if( index >= T::L::size ) {            return apply_helper<typename T::R>::apply(v,index - T::L::size);        } else {            return apply_helper<typename T::L>::apply(v,index);        }    }};// Original functionsinline int fun2(int x) {    return x;}inline int fun2(double x) {    return 0;   }inline int fun2(float x) {    return -1;   }// Adapted functionstypedef std::tuple<int,float> tup;inline int g0(const tup & t) { return fun2(std::get<0>(t)); }inline int g1(const tup & t) { return fun2(std::get<1>(t)); }inline int g2(const tup & t) { return fun2(std::get<2>(t)); }// Registrytypedef TypeList<   type_handler<tup,&g0>,type_handler<tup,&g1>,&g2>> registry;typedef MakeTree<registry> jump_table;int apply(const tup & t,size_t index) {    return apply_helper<jump_table>::apply(t,index);}// Demoint main() {    {        tup t{5,1.5,15.5f};        std::cout << apply(t,0) << std::endl;        std::cout << apply(t,1) << std::endl;        std::cout << apply(t,2) << std::endl;    }    {        tup t{10,2) << std::endl;    }    {        tup t{15,2) << std::endl;    }    {        tup t{20,2) << std::endl;    }}

住在Coliru:
http://coliru.stacked-crooked.com/a/3cfbd4d9ebd3bb3a

总结

以上是内存溢出为你收集整理的c – 切换语句可变模板扩展全部内容,希望文章能够帮你解决c – 切换语句可变模板扩展所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1253616.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存