g++ gives me strange function call in an *expected

2019-07-23 19:15发布

问题:

Here's the situation:

void funct( unsigned u, double d, float f )
{
        u = 12;
}
void funct( double u, int d, void* asd, float f )
{
        u = 13;
}

int main()
{
        const unsigned u = 123;
        double d = 123.123;
        float f = 123.123;

        funct( u, d, f, 123 );

        return 0;
}

gives me:

./src/test.cpp:19: error: no matching function for call to 'funct(const unsigned int&, double&, float&, int)'
./src/test.cpp:4: note: candidates are: void funct(unsigned int, double, float)
./src/test.cpp:8: note:                 void funct(double, int, void*, float)

It's absolutely expected error, as there's no suitable function to be called, OK, fine. But take a look at the compiler error:

                                                          V        V       V
no matching function for call to 'funct(const unsigned int&, double&, float&, int)

Why are these & there? When I make a correct call - everything is fine, and all parameters, as expected, are not passed as references.

Using Ubuntu 10.04, 64bit and g++ version 4.4.3

回答1:

You're passing a real variable which can be assigned to (an "lvalue") to the function. Of course you pass it by value, not by reference - but the point is, in your function call you would be able to also pass it by reference, because it's an lvalue.

Then: If you have a value of type int& (lvalue), you are allowed to send it to a function which accepts int (either rvalue or lvalue) - just not the other way round.



回答2:

The compiler does not know if you intend to pass your variables by value or by reference. It can't rule out the possibility that the correct function (the one you failed to declare) expects references.



回答3:

It tries to map the argument expressions to express them only in terms of types. So for lvalues of type T, it uses T&, and for rvalues of type T it uses T (unmodified).

Of course, an argument expression never has reference type (no expression can have reference type), but that's GCC's way to expressing that. For C++0x, there will be lvalues, xvalues and prvalues. GCC would probably use T& for the first and T for the latter two, or T&& for the second and T for the last.

Clang does a better job here

main1.cpp:16:9: error: no matching function for call to 'funct'
        funct( u, d, f, 123 );
        ^~~~~
main1.cpp:5:6: note: candidate function not viable: no known conversion from 'float' to 
                     'void *' for 3rd argument                                     
void funct( double u, int d, void* asd, float f )
     ^
main1.cpp:1:6: note: candidate function not viable: requires 3 arguments, but 4 were provided
void funct( unsigned u, double d, float f )
     ^
1 error generated.