Yantao Xie
Yantao Xie

Reputation: 12896

Why I cannot pass a functor defined in a function to another function?

I found the functor can be used to simulate defining a function within a function like this

using namespace std;
int main(int argc, char* argv[])
{
    struct MYINC {
        int operator()(int a) { return a+1; }
    } myinc;
    vector<int> vec;
    for (int i = 0; i < 10; i++) vec.push_back(myinc(i));
    return 0;
}

But If I passed it to an outside function, such as std::transform like the following example, I've got a compiling error saying error: no matching function for call to ‘transform(std::vector<int>::iterator, std::vector<int>::iterator, std::vector<int>::iterator, main(int, char**)::MYINC&)’

using namespace std;
int main(int argc, char* argv[])
{
    struct MYINC{
        int operator()(int a) { return a+1; }
    } myinc;
    vector<int> vec;
    for (int i = 0; i < 10; i++) vec.push_back(i);
    transform(vec.begin(), vec.end(), vec.begin(), myinc);
    return 0;
}

So I put the definition outside the main function and all is OK now.

using namespace std;
struct MYINC{
    int operator()(int a) { return a+1; }
} myinc;
int main(int argc, char* argv[])
{
    vector<int> vec;
    for (int i = 0; i < 10; i++) vec.push_back(i);
    transform(vec.begin(), vec.end(), vec.begin(), myinc);
    return 0;
}

Upvotes: 5

Views: 499

Answers (2)

6502
6502

Reputation: 114461

For reasons that aren't entirely clear to me there is (was) a well-known and quite annoying limitation in C++ 03 on which types you can use to instantiate a template.

Locally defined classes could not be used as parameters with templates, just because.

This by the way made quite difficult to make any decent use of the <algorithm> library because you could not keep the context of your code local, being forced instead to place all functors, comparators and the like at namespace level, making up funny names for them and placing them far from the point of use.

Upvotes: 1

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145204

Both versions compile fine with g++ 4.8.2, which is a C++11 compiler.

A C++03 compiler would however balk at instantiating a template with a local type, since that was not supported in C++03.

One solution, if that is indeed the root cause of the problem, is then to use a more recent compiler version or other compiler.

Another solution is to leverage that even in C++03 you can define a "real" function locally, by making it a static member function of a local class (in C++11 you can also do that by using a lambda expression).

However, except for dealing with such a problem, the functor has a general performance advantage over the "real" function, namely that with an object of a class instead of just a function pointer, and with the relevant operator() as inline, the compiler can optimize much better, because it knows the function implementation.

Upvotes: 6

Related Questions