Std :: bind and function templates

I'm currently trying to use functions std::bindto create std::function<void()>from a template

template<class Iterator>
void printRange(Iterator first, Iterator last) {
    std::copy(first, last, std::ostream_iterator<typename Iterator::value_type>(std::cout, " "));
    std::cout << std::endl;
}

Clear what i want

int main() {
    std::vector<int> v{1, 2, 3};
    auto f0 = std::bind(printRange, v.begin(), v.end()); // won't compile, of course
    f0();
    return 0;
}

I understand that this does not compile, and I need to create an instance of the function template before I can use it. For example, the following alternatives will work:

auto f1 = std::bind(printRange<std::vector<int>::const_iterator>, v.begin(), v.end());
auto f2 = std::bind(printRange<decltype(v.begin())>, v.begin(), v.end());
auto f3 = [&v]() { printRange(v.begin(), v.end()); };

I have already created a convenient function

template<class Iterator>
std::function<void()> makePrintRangeFunction(Iterator first, Iterator last) {
    return std::bind(printRange<Iterator>, first, last);
}

To facilitate the process:

auto f4 = makePrintRangeFunction(v.begin(), v.end());

I wonder if it is possible to create a more general generator std::function<void()>that takes a function template as the first argument and the function template arguments as a list of arguments of variable length? If you do not use the built-in language features, perhaps through a macro?

+5
3

, :

#include <functional>
#include <iostream>
#include <typeinfo>


template<typename ... T>
std::function<void()> makePrintRangeFunction(void (*f)(T...), T... param) {
    return std::bind(f, param...);
}

template<typename T, typename V>
void print(T type, V val)
{
    std::cout << typeid(type).name() << '\n' << val << '\n';
}

int main()
{
    int i = 5;
    double d = 10.5;
    auto f = makePrintRangeFunction(print, i, d);
    f();
}
+3

++ 14, :

template<typename F>
auto fungen(F f) {
  return [=](auto... args) { f(args...); };
}

:

int main() {
  std::vector<int> v {1, 2, 3, 4};
  auto f = fungen(printRange<std::vector<int>::iterator>);
  f(v.begin(), v.end());
}

Live Demo

+1

Perhaps the following code will help :)

template <class F, class... Args>
void test(F&& f, Args&&... args) {
 std::function<typename std::result_of<F(Args...)>::type()> task(
   std::bind(std::forward<F>(f), std::forward<Args>(args)...));
   task();
}
+1
source

Source: https://habr.com/ru/post/1625125/


All Articles