1

Problem: source code (see. below) is compiled MSVC , but does not compile g++.

#include <iostream>
using namespace std;

class B;
class A
{
friend class B;

private:
    int i;    
    A(int n) : i(n) { }

public :
    A(A& a) {   if (&a != this) *this = a;  }
    int display() { return i;}
};

class B
{
public :
    B() { }
    A func( int j)  {  return A(j); }
};

int main(int argc, char **argv)
{
    B b;
    A a(b.func((10)));
    cout << " a.i = " << a.display() << endl;

    return 0;
}

Output:

GNU g++ compilation message:
    g++ -c main.cpp
    main.cpp: In member function 'A B::func(int)':
    main.cpp:25:38: error: no matching function for call to 'A::A(A)'
             A func( int j)  {  return A(j); }
                                          ^
    main.cpp:25:38: note: candidates are:
    main.cpp:17:9: note: A::A(A&)
             A(A& a) {   if (&a != this) \*this = a;  }
             ^
    main.cpp:17:9: note:   no known conversion for argument 1 from 'A' to 'A&'
    main.cpp:14:9: note: A::A(int)
             A(int n) : i(n) { }
             ^
    main.cpp:14:9: note:   no known conversion for argument 1 from 'A' to 'int'
    main.cpp: In function 'int main(int, char\**)':
    ...

Why? Class B is a friend for class A then B has access to private constructor A(int i).

Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187

2 Answers2

3

Your copy constructor must take a const reference so it can bind to a temporary A:

 A(const A& a) { .... }

The C++ standard does not allow binding a non-const reference to a temporary. g++ is strict about this, while MSVC has an "extension" that breaks the rule.

Besides that, your implementation of the copy constructor looks strange. You should not be using the assignment operator there. For a class like A, you should use the implicitly generated copy constructor, in other words, remove your own:

class A
{
  friend class B;
private:
    int i;    
    A(int n) : i(n) { }

public :
    int display() const { return i;}
};
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
0

It is a bug of MS VC++. It shall not compile the code. The problem is that the error message of g++ is not cllear enough.

In fact the compiler tries to elide using of a copy constructor and to build the object directly in 'a' using constructor A(int n);. But that it will be possible an appropriate copy constructor shall be available. As a temporary object should be copied (if the ilision would not be used) then the copy constructor shall have const reference to object. That is instead of A(A& a); your copy constructor shall be declared as A( const A& a); If you will make the changes then g++ will compile the code.

The most simple way to define copy constructor for your example is to write

A( const A & ) = default;

However I am not sure whether your MS VC++ compiler supports this feature.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335