1

In the below example code, regardless of it is a POD, class A has a copy constructor and also the assignment operator is overloaded. foos and bars are entities of type A. Depending on how foo and bar are constructed, the compiler gives error messages in some cases when I use the assignment operator in the main code. The error messages are commented in the snipped code below.

I understand that the problem is related to the implicit use of the assignment operator. But, why foo1=bar1; is ok and foo2=bar2; is not?

Edit : It is clear from the comments that compilers interpret A foo(); as a function declaration not a ctor. This explains why I got first and second error messages in my code. However, the reason for the error message on the line A foo4 = A(2,3); is something different. It is related to the design of copy constructor and the object must be const.

(See: Why C++ copy constructor must use const object? )

I corrected the copy constructor as follow, A(const A &a) {x =a.x; y=a.y;}

Edit 2 : After toby-speight 's comment, I recompiled the same code (having copy constructor without 'const' object viz. A(A &a) {x =a.x; y=a.y;} ) by using gcc compiler with c++17. The error on the line A foo4 = A(2,3); disappeared.This shows that guaranteed copy elision is implemented in gcc (at least in gcc 7.3.1, which is the version I have been using).

#include <iostream>

class A{
 public:
    int x;
    int y;

    A(): x(0),y(0) {  }
    A(int xval, int yval): x(xval),y(yval) {  }

    //Copy constructor.
    A(A &a) {x =a.x; y=a.y; }

    //Assgnment operator overloading
    A& operator=(A &a){
        if (this !=&a){
            x=a.x;
            y=a.y;
        }
        return *this;
    }
};

int main(){

  A foo1(2,3);
  A bar1;
  foo1 = bar1;

  A foo2();
  A bar2();
  foo2 = bar2;  // error: cannot convert ‘A()’ to ‘A()’ in assignment

  A foo3(2,3);
  A bar3();
  foo3 = bar3;  // error: no match for ‘operator=’ (operand types are ‘A’ and ‘A()’)

  A foo4 = A(2,3); //<--- // error: cannot bind non-const lvalue reference of type ‘A&’ to an rvalue of type ‘A’
  A bar4;  //ok.          // note:   initializing argument 1 of ‘A::A(A&)’
  foo4 = bar4;

   return 0;
}
Community
  • 1
  • 1
  • Not sure if the above was the best duplicate - it boils down to the fact that `A foo2()` is declaring a function. – The Dark Aug 21 '18 at 00:54
  • 2
    `A foo2();` declares a function named `foo2` that returns an `A`. It does not define an `A` object. – Miles Budnek Aug 21 '18 at 00:54
  • So, `A foo3(2,3);` also decleres a function named `foo3`? – Gultekin Yegin Aug 21 '18 at 01:07
  • 1
    Because you are passing parameters, the compiler knows that you are declaring an object using those constructor parameters. When you don't pass any parameters, the syntax is the same between declaring an object and a function, so the compiler assumes you are declaring a function. The easiest fix is to just use `A foo2;` to declare an object which doesn't need constructor parameters. – The Dark Aug 21 '18 at 01:11
  • If you search for "most vexing parse", you'll find *lots* about variations of the same problem you've encountered. For a couple of examples: https://stackoverflow.com/q/1424510/179910, https://stackoverflow.com/q/31574575/179910 (but there are *many* more, both on SO and elsewhere). – Jerry Coffin Aug 21 '18 at 01:27
  • The part of your question that's not masked by the "most vexing parse" is because you're using C++14 (or earlier). From C++17, guaranteed copy elision allows this to compile despite the non-const reference argument (or GCC has a bug). I recommend you severely edit your code to remove the function declarations, so it focuses exclusively on the problem assignment where we create `foo4`. – Toby Speight Aug 22 '18 at 16:38

0 Answers0