C ++ compiler error C2751 - What exactly is causing it?

I am struggling with compiler error C2751 and am not quite sure what exactly is causing it. The following small code throws an error:

#include <iostream>  

class A {
public:
    A () { std::cout << "A constructed" << std::endl; };
    static A giveA () { return A (); }
};

class  B {
public:
    B (const A& a) { std::cout << "B constructed" << std::endl; }
};


int main () {

    B b1 = B (A::giveA ()); // works
    B b2 (B (A::giveA ())); // C2751
    B b3 (A::giveA ()); // works

}

      

Compiler output:

consoleapplication1.cpp(21): error C2751: 'A::giveA': the name of a function parameter cannot be qualified

Why can't I explicitly call the constructor for b2

?

+2


source to share


4 answers


This is the most troublesome parsing problem . Compiling for clang gives full diagnostics:

<source>:18:17: error: parameter declarator cannot be qualified
    B b2 (B (A::giveA ())); // C2751
             ~~~^

<source>:18:10: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
    B b2 (B (A::giveA ())); // C2751
         ^~~~~~~~~~~~~~~~~

<source>:18:11: note: add a pair of parentheses to declare a variable
    B b2 (B (A::giveA ())); // C2751
          ^
          (              )
1 warning and 1 error generated.
Compiler exited with result code 1

      



Execution as the compiler suggests to fix it:

B b2 ((B (A::giveA ()))); // no error 

      

+6




This particular instruction is ambiguous; then as you stated it could be either a function declaration or a variable definition.

Using extra parentheses should help - it becomes unambiguous since you cannot declare / call a function with double brackets:



B b1 = B( A::giveA () ); // works
B b2(( B( A::giveA() ) )); // works for me
B b3( A::giveA() ); // works

      

Also see here: https://en.wikipedia.org/wiki/Most_vexing_parse

+2


source


B b2 (B (A::giveA ()));

      

Even if you have a class copy constructor B

, you will still get this error, since the above line follows the rules of the function declaration grammar. Having parentheses around B(A::give())

solves your problem.

+2


source


Ah, the ol problem is the most troublesome parsing .

This line is here

B b2 (B (A::giveA ())); // C2751

      

interpreted as a function b2

that returns B

and accepts a function A::giveA

type parameter B()

. Error C2751 is caused by an invalid name A::giveA

: You cannot use a qualified name as a parameter name.

To copy the temporary object B

to b2

(which I believe is your intention) you can add more brackets

B b2 (( B (A::giveA ()) ));

      

or use curly braces (as long as no constructor exists that accepts initialization lists containing the type of the type being converted B

)

B b2 {B (A::giveA())};

      

+2


source







All Articles