i want write function takes arbitrary number of functions of form float(float, float)
, yields callable object (e.g. lambda expression) represents product (in mathematical sense) of these functions.
we can this, example, in following way:
template<typename... binaryfunctions> auto product_of(binaryfunctions... fs) { return [=](float x, float y) { return (... * fs(x, y)); }; }
however, until c++17, returned lambda not constexpr
when fs
are. so, question is: want keep fold expression, how can modify product_of
such returned callable object constexpr
in sense of c++14?
if want bend on backwards use fold expression, can still it. need auxiliary function class:
#include <tuple> #include <utility> template<typename... fs> class product_of_fn { std::tuple<fs...> fs; public: template<typename... fsfwd> constexpr explicit product_of_fn(fsfwd &&... fs) : fs{ std::forward<fsfwd>(fs)... } {} constexpr auto operator()(float x, float y) { return impl(x, y, std::make_index_sequence<sizeof...(fs)>{}); } private: template<std::size_t... is> constexpr auto impl(float x, float y, std::index_sequence<is...>) { return (... * std::get<is>(fs)(x, y)); } };
usage (using @vittorioromeo's example)
template<typename... fs> constexpr auto product_of(fs... fs) { return product_of_fn<std::decay_t<fs>...>{ std::forward<fs>(fs)... }; } template<int> struct adder { constexpr auto operator()(float x, float y) { return x + y; } }; int main() { auto f = product_of(adder<0>{}, adder<1>{}); static_assert(f(1, 2) == 3 * 3); }
the idea pretty same vittorio's, except use std::tuple
can use product_of
function function objects types final
, multiple functions of same type.
a std::index_sequence
used re-obtain parameter pack can fold expression.
simply converting vittorio's solution works well, caveats mentioned (none of fs
can final or same):
#include <utility> template<typename... fs> class product_of_fn : fs... { public: template<typename... fsfwd> constexpr explicit product_of_fn(fsfwd &&... fs) : fs{ std::forward<fsfwd>(fs) }... {} constexpr auto operator()(float x, float y) { return (... * static_cast<fs &>(*this)(x, y)); } };
Comments
Post a Comment