加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 通过索引在运行时访问std :: tuple元素的最佳方式

发布时间:2020-12-16 03:23:42 所属栏目:百科 来源:网络整理
导读:我的功能设计是通过运行时指定的索引来访问std :: tuple元素 templatestd::size_t _Index = 0,typename _Tuple,typename _Functioninline typename std::enable_if_Index == std::tuple_size_Tuple::value,void::typefor_each(_Tuple ,_Function){}templates
我的功能设计是通过运行时指定的索引来访问std :: tuple元素
template<std::size_t _Index = 0,typename _Tuple,typename _Function>
inline typename std::enable_if<_Index == std::tuple_size<_Tuple>::value,void>::type
for_each(_Tuple &,_Function)
{}

template<std::size_t _Index = 0,typename _Function>
inline typename std::enable_if < _Index < std::tuple_size<_Tuple>::value,void>::type
    for_each(_Tuple &t,_Function f)
{
    f(std::get<_Index>(t));
    for_each<_Index + 1,_Tuple,_Function>(t,f);
}

namespace detail { namespace at {

template < typename _Function >
struct helper
{
    inline helper(size_t index_,_Function f_) : index(index_),f(f_),count(0) {}

    template < typename _Arg >
    void operator()(_Arg &arg_) const
    {
        if(index == count++)
            f(arg_);
    }

    const size_t index;
    mutable size_t count;
    _Function f;
};

}} // end of namespace detail

template < typename _Tuple,typename _Function >
void at(_Tuple &t,size_t index_,_Function f)
{
    if(std::tuple_size<_Tuple> ::value <= index_)
        throw std::out_of_range("");

    for_each(t,detail::at::helper<_Function>(index_,f));
}

它具有线性复杂性.我怎么能得到O(1)的复杂性?

解决方法

假设您传递类似于通用lambda的东西,即具有重载函数调用运算符的函数对象:
#include <iostream>

struct Func
{
    template<class T>
    void operator()(T p)
    {
        std::cout << __PRETTY_FUNCTION__ << " : " << p << "n";
    }
};

您可以构建一个函数指针数组:

#include <tuple>

template<int... Is> struct seq {};
template<int N,int... Is> struct gen_seq : gen_seq<N-1,N-1,Is...> {};
template<int... Is> struct gen_seq<0,Is...> : seq<Is...> {};

template<int N,class T,class F>
void apply_one(T& p,F func)
{
    func( std::get<N>(p) );
}

template<class T,class F,int... Is>
void apply(T& p,int index,F func,seq<Is...>)
{
    using FT = void(T&,F);
    static constexpr FT* arr[] = { &apply_one<Is,T,F>... };
    arr[index](p,func);
}

template<class T,class F>
void apply(T& p,F func)
{
    apply(p,index,func,gen_seq<std::tuple_size<T>::value>{});
}

用法示例:

int main()
{
    std::tuple<int,double,char,double> t{1,2.3,4,5.6};
    for(int i = 0; i < 4; ++i) apply(t,i,Func{});
}

clang也接受一个应用于包含lambda表达式的模式的扩展:

static FT* arr[] = { [](T& p,F func){ func(std::get<Is>(p)); }... };

(虽然我不得不承认这看起来很奇怪)

g 4.8.1拒绝这一点.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读