c++ - Product of functions with a fold expression -


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