Optimal way to access std::tuple element in runtime by index

前端 未结 1 1479
故里飘歌
故里飘歌 2020-12-25 08:55

I have function at designed to access std::tuple element by index specified in runtime

template

        
相关标签:
1条回答
  • 2020-12-25 09:52

    Assuming you pass something similar to a generic lambda, i.e. a function object with an overloaded function call operator:

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

    The you can build an array of function pointers:

    #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, int index, F func)
    {
        apply(p, index, func, gen_seq<std::tuple_size<T>::value>{});
    }
    

    Usage example:

    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++ also accepts an expansion applied to a pattern that contains a lambda expression:

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

    (although I've to admit that looks really weird)

    g++4.8.1 rejects this.

    0 讨论(0)
提交回复
热议问题