Why does overloading a function with std::function require an intermediate variable

Viewed 69
#include <functional>

bool f1(int a, int b)
{
    return true;
}

int main()
{
    // This compiles
    std::function<bool()> f2 = std::function<bool()>(std::bind(f1, 1, 2));
    std::function<bool()> f1 = f2;

    // These don't compile
    //std::function<bool()> f1 = std::function<bool()>(std::bind(f1, 1, 2));
    //std::function<bool()> f1 = std::bind(f1, 1, 2);
    //std::function<bool()> f1(std::bind(f1, 1, 2));
}

I was trying to overload f1 by providing a std::function of the same name. However, I ran into this curious situation where an intermediate variable f2 must be used or else it doesn't compile. Why is that the case?

The error messages for the 3 cases are as follows

error: no matching function for call to ‘std::function<bool()>::function(std::_Bind_helper<false, std::function<bool()>&, int, int>::type)’
     std::function<bool()> f1 = std::function<bool()>(std::bind(f1, 1, 2));
error: conversion from ‘std::_Bind_helper<false, std::function<bool()>&, int, int>::type’ {aka ‘std::_Bind<std::function<bool()>(int, int)>’} to non-scalar type ‘std::function<bool()>’ requested
     std::function<bool()> f1 = std::bind(f1, 1, 2);
                                ~~~~~~~~~^~~~~~~~~~
error: no matching function for call to ‘std::function<bool()>::function(std::_Bind_helper<false, std::function<bool()>&, int, int>::type)’
     std::function<bool()> f1(std::bind(f1, 1, 2));
                                                 ^

Edit 1

It appears that even with the first case where it compiles, it does not accomplish overloading as I hoped due to the original bool f1(int a, int b) being no longer accessible. But I would still like to know why the compiler compiles for only some of the above cases.


Edit 2 (after closing)

While it turns out the reason for this behaviour was actually quite silly and has nothing to do with std::function, I'll attempt to add some salvageable value by posting how I accomplished what I wanted to do: by namespacing the original f1 function

namespace
{
bool f1(int a, int b)
{
    printf("blah\n");
    return true;
}
}

int main()
{
    // This works
    //std::function<bool()> f2 = std::function<bool()>(std::bind(f1, 1, 2));
    //std::function<bool()> f1 = f2;

    // These work also
    std::function<bool()> f1 = std::function<bool()>(std::bind(::f1, 1, 2));
    //std::function<bool()> f1 = std::bind(::f1, 1, 2);
    //std::function<bool()> f1(std::bind(::f1, 1, 2));
    //
    
    f1();
    ::f1(1,2);
}
1 Answers

Variables enter scope as soon as they're declared. That means that they're in scope for their initializer.

In std::function<bool()> f1 = std::bind(f1, 1, 2);, the f1 on the right-hand side of the = refers to the f1 you declared on the left-hand side.

Note that this is not in any way unique to std::function or anything. int a = a; is perfectly well-formed syntactically (though its behavior is undefined).

Related