Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::bind and function templates

I am currently trying to use std::bind to create a std::function<void()> from the function 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;
}

Conceptually, what I want is

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 have to instantiate the function template before I can actually use it. For example, the following alternatives would 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 already created a convenience function

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

to ease the process:

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

I wonder if it is possible to create a more generic std::function<void()> generator, accepting a function template as a first argument and the function template arguments as a variable-length argument list? If not using built-in language features, maybe via a macro?

like image 852
Marcel Avatar asked Jan 20 '16 13:01

Marcel


People also ask

Can templates be used for functions?

Templates Specialization is defined as a mechanism that allows any programmer to use types as parameters for a class or a function. A function/class defined using the template is called a generic function/class, and the ability to use and create generic functions/classes is one of the critical features of C++.

What does std :: bind do in C++?

std::bind is for partial function application. That is, suppose you have a function object f which takes 3 arguments: f(a,b,c); You want a new function object which only takes two arguments, defined as: g(a,b) := f(a, 4, b);

How do you call a template function in C++?

A function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

What are function templates?

Function templates are similar to class templates but define a family of functions. With function templates, you can specify a set of functions that are based on the same code but act on different types or classes. The following function template swaps two items: C++ Copy.


2 Answers

As long as you do not need to have template function return type, you can do this:

#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();
}
like image 118
Revolver_Ocelot Avatar answered Sep 20 '22 04:09

Revolver_Ocelot


Maybe 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();
}
like image 21
Tommy Avatar answered Sep 21 '22 04:09

Tommy