By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,440 Members | 1,420 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,440 IT Pros & Developers. It's quick & easy.

Help with a compile problem

P: n/a
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

May 30 '07 #1
Share this Question
Share on Google+
8 Replies


P: n/a
de**********@grog.net wrote:
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
May 30 '07 #2

P: n/a
anon wrote:
de**********@grog.net wrote:
>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).
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.
May 30 '07 #3

P: n/a
de**********@grog.net wrote:
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
May 30 '07 #4

P: n/a
On May 30, 12:07 pm, Fei Liu <fei...@aepnetworks.comwrote:
derek.goo...@grog.net wrote:
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
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.

May 30 '07 #5

P: n/a
On May 30, 11:44 am, anon <a...@no.nowrote:
anon wrote:
derek.goo...@grog.net wrote:
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).

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.

May 30 '07 #6

P: n/a
On May 30, 10:30 pm, derek.goo...@grog.net wrote:
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.

May 31 '07 #7

P: n/a

On 5/30/07 5:08 PM, in article
11**********************@w5g2000hsg.googlegroups.c om, "Pete C"
<5g*******@sneakemail.comwrote:
On May 30, 10:30 pm, derek.goo...@grog.net wrote:
>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.
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

May 31 '07 #8

P: n/a
On May 31, 2:08 am, Pete C <5gv7rq...@sneakemail.comwrote:
On May 30, 10:30 pm, derek.goo...@grog.net wrote:
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.
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.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 31 '07 #9

This discussion thread is closed

Replies have been disabled for this discussion.