valores una tipos retornan referencia que por parametros llamar funciones funcion ejemplos ejemplo como arreglos c++ c++11 lambda variadic-templates template-meta-programming

c++ - tipos - ¿Es posible devolver una variable LambD desde una plantilla de función?



tipos de funciones en c++ (3)

En C ++ 11, lo siguiente funciona si está dispuesto a crear manualmente el objeto de función:

template <typename F> struct min_on_t { min_on_t(F f) : f(f) {} template <typename T, typename... Ts> auto operator ()(T x, Ts... xs) -> typename std::common_type<T, Ts...>::type { // Magic happens here. return f(x); } private: F f; }; template <typename F> auto min_on(F f) -> min_on_t<F> { return min_on_t<F>{f}; }

Y luego llámalo:

auto minimum = min_on(mod7)(2, 8, 17, 5);

Para usar lambdas en C ++ 14, debe omitir el tipo de retorno final porque no puede especificar el tipo de lambda sin asignarlo primero a una variable, ya que una expresión lambda no puede aparecer en un contexto sin evaluar .

template <typename F> auto min_on(F f) { return [f](auto x, auto... xs) { using rettype = std::common_type_t<decltype(x), decltype(xs)...>; using f_rettype = decltype(f(x)); rettype result = x; f_rettype result_trans = f(x); (void)std::initializer_list<int>{ (f(xs) < result_trans ? (result = static_cast<rettype>(xs), result_trans = f(xs), 0) : 0)...}; return result; }; }

Tengo el siguiente código (c ++ 11):

template <typename F, typename FirstT, typename... FIn> auto min_on(F f, FirstT first, FIn... v) -> typename std::common_type<FirstT, FIn...>::type { using rettype = typename std::common_type<FirstT, FIn...>::type; using f_rettype = decltype(f(first)); rettype result = first; f_rettype result_trans = f(first); f_rettype v_trans; (void)std::initializer_list<int>{ ((v_trans = f(v), v_trans < result_trans) ? (result = static_cast<rettype>(v), result_trans = v_trans, 0) : 0)...}; return result; }

Lo que básicamente devuelve el result del argumento que produjo el valor mínimo para la expresión f(result) . Esto se puede llamar así:

auto mod7 = [](int x) { return x % 7; }; auto minimum = min_on(mod7, 2, 8, 17, 5); assert( minimum == 8); // since 8%7 = 1 -> minimum value for all arguments passed

Ahora me gustaría usar esto de una manera ''al curry'' para poder obtener un lambda min_on de min_on y luego llamarlo con argumentos (que podría recibir más adelante), así:

auto mod7 = [](int x) { return x % 7; }; auto f_min = min_on(mod7); auto minimum = f_min(2, 8, 17, 5); // or auto minimum = min_on(mod7)(2, 8, 17, 5);

¿Es esto posible?


En C ++ 14 esto es fácil.

template<class F> auto min_on( F&& f ) { return [f=std::forward<F>(f)](auto&& arg0, auto&&...args) { // call your function here, using decltype(args)(args) to perfect forward }; }

Muchos compiladores obtuvieron auto deducción de tipo de devolución auto y argumentos en lambdas que funcionaban antes del soporte completo de C ++ 14. Entonces, un compilador C ++ 11 nominal podría compilar esto:

auto min_on = [](auto&& f) { return [f=decltype(f)(f)](auto&& arg0, auto&&...args) { // call your function here, using decltype(args)(args) to perfect forward }; }

en C ++ 11:

struct min_on_helper { template<class...Args> auto operator()(Args&&...args) -> decltype( min_on_impl(std::declval<Args>()...) ) { return min_on_impl(std::forward<Args>(args)...); } };

es repetitivo. Esto nos permite pasar todo el conjunto de sobrecarga de min_on_impl como un solo objeto.

template<class F, class T> struct bind_1st_t { F f; T t; template<class...Args> typename std::result_of<F&(T&, Args...)>::type operator()(Args&&...args)&{ return f( t, std::forward<Args>(args)... ); } template<class...Args> typename std::result_of<F const&(T const&, Args...)>::type operator()(Args&&...args)const&{ return f( t, std::forward<Args>(args)... ); } template<class...Args> typename std::result_of<F(T, Args...)>::type operator()(Args&&...args)&&{ return std::move(f)( std::move(t), std::forward<Args>(args)... ); } }; template<class F, class T> bind_1st_t< typename std::decay<F>::type, typename std::decay<T>::type > bind_1st( F&& f, T&& t ) { return {std::forward<F>(f), std::forward<T>(t)}; }

nos da bind_1st .

template<class T> auto min_on( T&& t ) -> decltype( bind_1st( min_on_helper{}, std::declval<T>() ) ) { return bind_1st(min_on_helper{}, std::forward<T>(t)); }

es modular y resuelve su problema: tanto min_on_helper como bind_1st se pueden probar de forma independiente.

También puede reemplazar bind_1st con una llamada a std::bind , pero en mi experiencia, las peculiaridades de std::bind me hacen extremadamente cauteloso al recomendar eso a cualquiera.


No estoy seguro en C ++ 11, pero en C ++ 14, puedes crear un lambda para envolver tu función en:

auto min_on_t = [](auto f) { return [=](auto ... params) { return min_on(f, params...); }; }; auto min_t = min_on_t(mod7); auto minimum = min_t(2, 8, 17, 5);

Vivir en coliru