简体   繁体   中英

Pass templated function as a std::function and choose template argument later

I am trying to construct a function tune that takes a templated function via std::function and initializes a series of that function based on a std::integer_sequence . I am not sure whether this is possible, and I am stuck. I made a working example that shows what I aim to achieve: a generic function that takes another function and an integer list as an argument. I would like to be able to use the syntax that is in the two lines commented out in the bottom, because with the working code, I have to make a tune function for each function.

#include <iostream>
#include <functional>

template<int I> void print_value() { std::cout << I << std::endl; }
template<int I> void print_value_squared() { std::cout << I*I << std::endl; }

template<int... Is>
void tune_print_value(std::integer_sequence<int, Is...>)
{
    (print_value<Is>(), ...);
}

/* NOT SURE HOW TO DO THIS...
template<class Func&&, int... Is>
void tune(std::function<Func> f, std::integer_sequence<int, Is...)
{
    (f<Is>(), ...);
}
*/

int main()
{
    std::integer_sequence<int, 1, 2, 3> is;
    tune_print_value(is);

    // I would like:
    // tune(print_value, is);
    // tune(print_value_squared, is);

    return 0;
}

This is not possible with a simple function pointer or std::function (as it can only point to one instance of a particular template!) but what you can do though is to wrap each function print_value or print_value_squared in a corresponding struct

struct print_value {  
  template <int I>
  static constexpr int impl() {
    std::cout << I << std::endl;
    return I;
  }
};

This struct then holds the templated implementation as a static member function with a predefined name such as impl (sadly you can't use operator () like for a functor as it is not allowed to be static )

Your tune function then takes this struct as a template argument and "magically" (in C++20 you could create a concept for this as follows , prior to it you might use SFINAE and std::enable_if as follows ) accesses the wrapped template function impl .

template<class Func, int... Is>
auto tune(std::integer_sequence<int, Is...>) {
  return (Func::template impl<Is>(), ...);
}

You will need the keyword template as a qualifier in this case to tell the compiler that the member function is a template.

You can then call the tune function like

tune<print_value>(is);

Try it here with a static member function impl or here with a non-static operator() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM