copy ctor being private and compilation error

  • Thread starter subramanian100in
  • Start date
S

subramanian100in

Consider the following program x.cpp:

#include <cstdlib>
#include <iostream>

using namespace std;

class Test
{
public:
explicit Test(int arg = 10);
ostream& writeTo(ostream& os) const;
private:
Test(const Test& rhs);
int val;
};

inline Test::Test(int arg) : val(arg)
{
cout << "Test one-argument-ctor called" << endl;
}

inline ostream& Test::writeTo(ostream& os) const
{
return os << val;
}

inline ostream& operator<<(ostream& os, const Test& obj)
{
return obj.writeTo(os);
}

int main()
{
const Test& ref = Test();
cout << ref << endl;

return EXIT_SUCCESS;
}

When I compile this program as
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp

I get the following compilation error:
x.cpp: In function `int main()':
x.cpp:12: error: `Test::Test(const Test&)' is private
x.cpp:33: error: within this context

Though the copy ctor of Test is private, the statement
const Test& ref = Test();
involves only taking a 'const reference' to the temporary Test object
created by Test() on the RHS. Since only a reference is made, why does
this statement require the copy ctor ?
Kindly clarify, if necessary with a program example.

Thanks
V.Subramanian
 
I

Ian Collins

Consider the following program x.cpp:
int main()
{
const Test& ref = Test();
cout<< ref<< endl;

return EXIT_SUCCESS;
}

When I compile this program as
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp

I get the following compilation error:
x.cpp: In function `int main()':
x.cpp:12: error: `Test::Test(const Test&)' is private
x.cpp:33: error: within this context

Though the copy ctor of Test is private, the statement
const Test& ref = Test();
involves only taking a 'const reference' to the temporary Test object
created by Test() on the RHS. Since only a reference is made, why does
this statement require the copy ctor ?

It appears to be a bug in the version (3.4.x?) of gcc you are using.
 
K

Kai-Uwe Bux

Ian said:

Just to be more explicit, I recall the declaration of Test:

class Test
{
public:
explicit Test(int arg = 10);
ostream& writeTo(ostream& os) const;
private:
Test(const Test& rhs);
int val;
};

Note the private copy constructor.

It appears to be a bug in the version (3.4.x?) of gcc you are using.

It's not a bug. The code is invalid in C++98 and C++03 by [8.5.3/5] which
requires the copy constructor to be visibile. The compiler is free (but not
required) to make a copy of the object before initializing the reference.
The bug is in newer g++ versions (starting with the 4.3 series or
thereabout).

The code will be legal in C++0x.


Best

Kai-Uwe Bux
 
I

Ian Collins

Ian said:

Just to be more explicit, I recall the declaration of Test:

class Test
{
public:
explicit Test(int arg = 10);
ostream& writeTo(ostream& os) const;
private:
Test(const Test& rhs);
int val;
};

Note the private copy constructor.

It appears to be a bug in the version (3.4.x?) of gcc you are using.

It's not a bug. The code is invalid in C++98 and C++03 by [8.5.3/5] which
requires the copy constructor to be visibile. The compiler is free (but not
required) to make a copy of the object before initializing the reference.
The bug is in newer g++ versions (starting with the 4.3 series or
thereabout).

Ah, OK. I missed "The constructor that would be used to make the copy
shall be callable whether or not the copy is actually done."
 
G

Gennaro Prota

On 03/08/2010 6.12, (e-mail address removed), India wrote:
[...]
int main()
{
const Test& ref = Test();
cout<< ref<< endl;

return EXIT_SUCCESS;
}

When I compile this program as
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp

I get the following compilation error:
x.cpp: In function `int main()':
x.cpp:12: error: `Test::Test(const Test&)' is private
x.cpp:33: error: within this context

Though the copy ctor of Test is private, the statement
const Test& ref = Test();
involves only taking a 'const reference' to the temporary Test object
created by Test() on the RHS. Since only a reference is made, why does
this statement require the copy ctor ?
Kindly clarify, if necessary with a program example.

I don't know if this is in the FAQ but it should be :) C++98
required this.

And although it allowed the copy to be omitted it required the
copy constructor to be accessible anyway, so that your code
would not suddenly broke because you switched from a compiler
that omitted the copy to one that didn't.

C++0x has a different rule; see core issue 391:

<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#391>
 
S

subramanian100in

* Kai-Uwe Bux said:

Just to be more explicit, I recall the declaration of Test:

class Test
{
public:
explicit Test(int arg = 10);
ostream& writeTo(ostream& os) const;
private:
Test(const Test& rhs);
int val;
};

Note the private copy constructor.


It appears to be a bug in the version (3.4.x?) of gcc you are using.

It's not a bug. The code is invalid in C++98 and C++03 by [8.5.3/5] which
requires the copy constructor to be visibile. The compiler is free (but not
required) to make a copy of the object before initializing the reference.
The bug is in newer g++ versions (starting with the 4.3 series or
thereabout).

The code will be legal in C++0x.

Best

Kai-Uwe Bux

Thanks for your clarification. In the above program suppose I replace
the line
const Test& ref = Test();
with
Test obj;
const Test& ref = obj;
the program compiles fine. Here is the complete modified program:

#include <cstdlib>
#include <iostream>

using namespace std;

class Test
{
public:
explicit Test(int arg = 10);
ostream& writeTo(ostream& os) const;
private:
Test(const Test& rhs);
int val;
};

inline Test::Test(int arg) : val(arg)
{
cout << "Test one-argument-ctor called" << endl;
}

inline ostream& Test::writeTo(ostream& os) const
{
return os << val;
}

inline ostream& operator<<(ostream& os, const Test& obj)
{
return obj.writeTo(os);
}

int main()
{
Test obj;
const Test& ref = obj; // note the change here
cout << ref << endl;

return EXIT_SUCCESS;
}

Suppose I compile this program with g++3.4.3 as
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp

it compiles fine and produces the output:
Test one-argument-ctor called
10

My question is why doesn't the compiler allow
const Test& ref = Test();
but it allows
Test obj;
const Test& ref = obj; // note the change here
I am unable to understand the difference. Kindly clarify the reason
regarding how this modified program gets compiled while the earlier
version doesn't.

Thanks
V.Subramanian
 
S

SG

* Kai-Uwe Bux said:
It's not a bug. The code is invalid in C++98 and C++03 by [8.5.3/5] which
requires the copy constructor to be visibile. The compiler is free (but not
required) to make a copy of the object before initializing the reference.
The bug is in newer g++ versions (starting with the 4.3 series or
thereabout).
The code will be legal in C++0x.

Thanks for your clarification. In the above program suppose I replace
the line
    const Test&  ref = Test();
with
    Test obj;
    const Test&  ref = obj;
the program compiles fine.
[snip]

My question is why doesn't the compiler allow
const Test& ref = Test();
but it allows
Test obj;
const Test& ref = obj; // note the change here

For some reason C++98 only requires an object to be copyable if you
try to initialize a reference with an *rvalue* expression. In your
case Test() is such an *rvalue* whereas obj is an *lvalue*. Your
example with 'obj' is really valid C++. As it has already been said,
this restriction will go away in C++0x. I suppose, that's because none
of the current compilers actually need to use the copy ctor in both of
these cases.

Cheers!
SG
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top