Search code examples
c++c++11function-pointersstd-function

error passing a std::function vs a function pointer as a parameter


I have the following piece of code, in which I declare 2 functions that take a function as a parameter (one by using std::function, the other one by using a pointer to a function). The function taken as a parameter has to have the prototype std::complex<double>(const std::complex<double>&). An example of such a parameter is std::sqrt in C++11, see http://en.cppreference.com/w/cpp/numeric/complex/sqrt . Now, I have absolutely no clue why the function that takes a pointer-to-function works (i.e. g_of_ten), whereas the other one, that takes a std::function as a parameter, doesn't (i.e. f_of_ten). If I uncomment the line

//cout << f_of_ten(std::sqrt) << endl; // ERROR here!!!

I get the error

 error: no matching function for call to 'f_of_ten'
        cout << f_of_ten(std::sqrt) << endl; // ERROR here!!!
                ^~~~~~~~
    /Users/vlad/minimal.cpp:10:6: note: candidate function not viable: no overload of 'sqrt' matching 'std::function<cplx (const cplx &)> &' for 1st argument
    cplx f_of_ten(std::function<cplx(const cplx &)>& x)
     ^
    1 error generated.

I am completely puzzled why this is happening, I though that std::function is really a wrapper for all kinds of functors (INCLUDING standard functions). Any help is more than welcome! Below is the code:

#include <cmath>
#include <complex>
#include <functional>
#include <iostream>

using namespace std;

using cplx = complex<double>; // to save some typing

cplx f_of_ten(std::function<cplx(const cplx &)> x) // the problematic one
{
    return x(10);
}

cplx g_of_ten(cplx(*x)(const cplx &)) // this works
{
    return (*x)(10);
}


int main()
{
    //cout << f_of_ten(std::sqrt) << endl; // compile ERROR here!!!
    cout << g_of_ten(std::sqrt) << endl;
}

PS: I, of course, also tried cout << f_of_ten(&std::sqrt) << endl;, same story, compile time error.

@Yakk,

this works fine:

#include <cmath>
#include <complex>
#include <functional>
#include <iostream>
#include <valarray>

using cplx = std::complex<double>; // to save some typing

cplx f_of_ten(std::function<cplx(const cplx &)> x) // the problematic one
{
    return x(10);
}

cplx g_of_ten(cplx(*x)(const cplx &)) // this works
{
    return (*x)(10);
}


int main()
{
    //cout << f_of_ten(std::sqrt<double>) << endl; // compile ERROR here!!!
    std::cout << g_of_ten(std::sqrt) << std::endl;
}

Solution

  • Bad idea, see comments and edit!

    The std::sqrt for complex numbers is a template, if you use std::sqrt<double> your code works.

    Not to sure why the g... variant works thou.

    Edit to salvage this answer:

    You can use a lambda to select the correct sqrt like

    std::cout << f_of_ten([](cplx x){return std::sqrt(x);}) << std::endl;
    

    Now template argument deduction and overload resolution will take place, select the right sqrt and pack it in the lambda which binds to std::function.