1

I'm not familiar with pointer to functions and I'm currently making some tests. But in the following program, I don't understand why the first version works and why the second version does not compile. What would be the correct syntax ?

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

template<typename Type> 
void display(const std::vector<Type>& v)
{
    if (!v.empty()) {
        for (unsigned int i = 0; i < v.size()-1; ++i)
            std::cout<<v[i]<<" ";
        std::cout<<v[v.size()-1];
    }
}

// Compiles 
template<typename Type> 
void apply1(std::vector<Type>& v, void(f)(Type*, Type*, Type))
{
    f(&*v.begin(), &*v.end(), 0);
}

// Does not compile
template<typename Type> 
void apply2(std::vector<Type>& v, std::function<void(Type*, Type*, Type)> f)
{
    f(&*v.begin(), &*v.end(), 0);
}

int main()
{
    std::vector<double> v = {1., 2., 3., 4., 5., 6.};
    display(v); std::cout<<std::endl;
    apply1(v, std::iota);
    display(v); std::cout<<std::endl;
    apply2(v, std::iota);
    display(v); std::cout<<std::endl;
    return 0;
}

The error is the following :

error: cannot resolve overloaded function 'iota' based on conversion to type 'std::function<void(double*, double*, double)>'
Vincent
  • 57,703
  • 61
  • 205
  • 388

1 Answers1

3

A function pointer provides what I call a conversion context. It explicitly states which of the overloads is meant, whilst std::function does not. The constructor of std::function takes in any callable entity and as such provides no context to disambiguate which overload is meant. See also this question.

To manually disambiguate, either cast the function pointer

apply2(v, static_cast<void(*)(double*,double*,double)>(std::iota));

or use a named function pointer

void (*iota)(double*, double*, double) = std::iota;
apply2(v, iota);

or use a lambda

apply2(v, [](double* f, double* l, double d){ std::iota(f, l, d); });
Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • So how can I modify `apply2` or its call to pass an algorithm like `std::iota` ? – Vincent Nov 05 '12 at 04:38
  • Thanks. But I have another question : In the case where I call a function and not a function template : are the two implementations "equivalent" (apart from the fact that std::function is more "powerful") ? – Vincent Nov 05 '12 at 04:48
  • @Vincent: Depends on what you define as *equivalent*, I guess. `std::function` can contain *any* callable entity, but also has indirection and possible allocation overhead. – Xeo Nov 05 '12 at 04:52