Help with a compile problem

D

derek.google

I have some production code that doesn't compile with GCC 3.4 but
works with GCC 3.3, VC8, and Comeau, so I'm wondering if this is a
compiler issue or if I'm doing something wrong. Stripped down, this is
the code in question:

class Foo {
public:
Foo() {}
private:
Foo(const Foo&); // Line 5, noncopyable by design
};

const Foo& operator<<(const Foo& foo, int) {
return foo;
}

int main() {
Foo() << 42; // Line 13
}

The error is this:

test.cpp:5: error: `Foo::Foo(const Foo&)' is private
test.cpp:13: error: within this context

What I don't understand is why the compiler is trying to invoke the
copy ctor in the first place. It seems like there shouldn't be any
copying going on, so GCC shouldn't care that the copy ctor is private.

Thanks.

Derek
 
A

anon

I have some production code that doesn't compile with GCC 3.4 but
works with GCC 3.3, VC8, and Comeau, so I'm wondering if this is a
compiler issue or if I'm doing something wrong. Stripped down, this is
the code in question:

Compiler issue - try using the latest gcc (4.1.2 or 4.2.0).
class Foo {
public:
Foo() {}
private:
Foo(const Foo&); // Line 5, noncopyable by design
};

const Foo& operator<<(const Foo& foo, int) {
return foo;
}

int main() {
Foo() << 42; // Line 13
}

Change your main to:

int main() {
Foo a;
a << 42; // Line 13
}

or change your class to this:

class Foo {
public:
Foo() {}
const Foo& operator<<(int) {
return *this;
}
private:
Foo(const Foo&); // Line 5, noncopyable by design
};

int main() {
Foo() << 42; // Line 13
}

What I don't understand is why the compiler is trying to invoke the
copy ctor in the first place. It seems like there shouldn't be any
copying going on, so GCC shouldn't care that the copy ctor is private.

You are creating temporary, but I am not sure what exactly is going on
 
A

anon

anon said:
Compiler issue - try using the latest gcc (4.1.2 or 4.2.0).

Sorry. To be more precise: you are doing something wrong, but it is a
compilers issue with gcc 3.3, VC8 and Comeau that they allow that thing
to be compiled.
 
F

Fei Liu

I have some production code that doesn't compile with GCC 3.4 but
works with GCC 3.3, VC8, and Comeau, so I'm wondering if this is a
compiler issue or if I'm doing something wrong. Stripped down, this is
the code in question:

class Foo {
public:
Foo() {}
private:
Foo(const Foo&); // Line 5, noncopyable by design
};

const Foo& operator<<(const Foo& foo, int) {
return foo;
}

int main() {
Foo() << 42; // Line 13
}

The error is this:

test.cpp:5: error: `Foo::Foo(const Foo&)' is private
test.cpp:13: error: within this context

What I don't understand is why the compiler is trying to invoke the
copy ctor in the first place. It seems like there shouldn't be any
copying going on, so GCC shouldn't care that the copy ctor is private.

Thanks.

Derek
There shouldn't be any copying involved, definitely a compiler issue in
my book.

F
 
D

derek.google

There shouldn't be any copying involved, definitely a compiler issue in
my book.

F

That was my impression also. Naturally it wasn't hard to change the
code to work by using a named variable instead of a temporary, but it
didn't seem like the copy ctor should be in play. Both GCC 3.4 and
4.2 seem to want the copy ctor to be available, though GCC 3.3,
Comeau, and VC8/SP1 do not.
 
D

derek.google

Sorry. To be more precise: you are doing something wrong, but it is a
compilers issue with gcc 3.3, VC8 and Comeau that they allow that thing
to be compiled.

Not sure I understand. I'm not copying anything, so what exactly is
it that's wrong? That the class Foo is actually non-copyable by
design, and since there is no copy that I can see, the compiler should
not require a public copy ctor just because I'm using a temporary
object.
 
P

Pete C

Not sure I understand. I'm not copying anything, so what exactly is
it that's wrong? That the class Foo is actually non-copyable by
design, and since there is no copy that I can see, the compiler should
not require a public copy ctor just because I'm using a temporary
object.

Yes it should - in fact, it *has* to require an accessible copy ctor.

Your expression "Foo()" is an rvalue (section 3.10.6 of the standard).
When you pass it to your operator<<, you are binding an rvalue to a
const reference (covered by section 8.5.3 of the standard). In this
case the compiler is given 2 options by the standard:

1) bind the reference directly to the rvalue, or
2) construct a new temporary object from the the rvalue object, and
bind the reference to the temporary object.

As it happens, g++ chooses option 1. But the standard says "The
constructor that would be used to make the copy shall be callable
whether or not the copy is actually done." And you have made yours
private.

So g++ is correct to complain, and the other compilers are wrong to
accept your code. FWIW I don't understand the rationale for option (2)
above, but there you have it.
 
G

Greg Herlihy

Yes it should - in fact, it *has* to require an accessible copy ctor.

Your expression "Foo()" is an rvalue (section 3.10.6 of the standard).
When you pass it to your operator<<, you are binding an rvalue to a
const reference (covered by section 8.5.3 of the standard). In this
case the compiler is given 2 options by the standard:

1) bind the reference directly to the rvalue, or
2) construct a new temporary object from the the rvalue object, and
bind the reference to the temporary object.

This requirement never made much sense - and it has in fact been eliminated
in the current C++ draft Standard. So I would recommend compiling with a C++
compiler that has been updated to the more sensible behavior.
As it happens, g++ chooses option 1. But the standard says "The
constructor that would be used to make the copy shall be callable
whether or not the copy is actually done." And you have made yours
private.

But is a public copy constructor that is never defined still "callable"? How
would the compiler know whether or not the constructor is callable without
actually calling it?
So g++ is correct to complain, and the other compilers are wrong to
accept your code. FWIW I don't understand the rationale for option (2)
above, but there you have it.

I doubt anyone else much understand this bizarre requirement either - which
is probably why it has been dropped.

Greg
 
J

James Kanze

On May 30, 10:30 pm, (e-mail address removed) wrote:
Yes it should - in fact, it *has* to require an accessible copy ctor.
Your expression "Foo()" is an rvalue (section 3.10.6 of the standard).
When you pass it to your operator<<, you are binding an rvalue to a
const reference (covered by section 8.5.3 of the standard). In this
case the compiler is given 2 options by the standard:
1) bind the reference directly to the rvalue, or
2) construct a new temporary object from the the rvalue object, and
bind the reference to the temporary object.
As it happens, g++ chooses option 1. But the standard says "The
constructor that would be used to make the copy shall be callable
whether or not the copy is actually done." And you have made yours
private.
So g++ is correct to complain, and the other compilers are wrong to
accept your code. FWIW I don't understand the rationale for option (2)
above, but there you have it.

It's related to the lifetime of temporaries. Consider something
like the following:

struct B {} ;
struct A { B b ; } ;

A f() ;

void
g()
{
B const& b = f().b ;
// uses b...
}

According to the standard, the lifetime of the object bound to
the reference in g is until the end of the function. But the
lifetime of the A object returned by f() must end at the end of
teh full expression. And the only way to destruct the A object
without destructing the B object bound to b is by making a copy.
(Both G++ and VC++ do copy in the above case, as required by the
standard.)

Presumably, the authors of the standard didn't want to make
special cases, and describe in full detail when and when not the
copy would occur, so the simply made it up to the implementation
in all cases. And required the copy constructor to be
accessible just in case.
 

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

No members online now.

Forum statistics

Threads
474,294
Messages
2,571,511
Members
48,198
Latest member
couriermedicine

Latest Threads

Top