c++ templates c++11 template-meta-programming stdtuple

c++ - Forma óptima de acceder al elemento std:: tuple en tiempo de ejecución por índice



templates c++11 (1)

Tengo la función diseñada para acceder al elemento std :: tuple por índice especificado en tiempo de ejecución

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 _Tuple, 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)); }

Tiene complejidad lineal. ¿Cómo puedo lograr O (1) complejidad?


Suponiendo que pasa algo similar a un lambda genérico, es decir, un objeto de función con un operador de llamada de función sobrecargado:

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

El puede construir una matriz de indicadores de funció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, int index, F func) { apply(p, index, func, gen_seq<std::tuple_size<T>::value>{}); }

Ejemplo de uso:

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 ++ también acepta una expansión aplicada a un patrón que contiene una expresión lambda:

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

(Aunque tengo que admitir que se ve muy raro)

g ++ 4.8.1 rechaza esto.