Topic: private copy constructor and reference args


Author: John Salmon <jsalmon@thesalmons.org>
Date: Sat, 11 Aug 2007 20:47:35 CST
Raw View
I've got a class with a private copy constructor
that I'd like to pass as a reference argument to a
function.

Gcc is unhappy with the following code unless I create an explicit
temporary.  Comeau's online compiler seems to think it's fine.  It
looks OK to me, too.  Since the argument to func() is a reference to
Foo, there's no need for the compiler to copy-construct a temporary.
Or is there?  Is gcc correct to complain?  Or is comeau correct to
accept this?

<snip>
class Foo {
   Foo(const Foo& f);
public:
   Foo() {}
};

void
func( const Foo& foo){
}

int
main(int argc, char **argv){
#ifndef EXPLICIT_TEMPORARY
   func(Foo());
#else
   Foo f;
   func(f);
#endif
   return 0;
}
</snip>

Gcc (4.1.1) says:

[jsalmon@river junk]$ gcc noncopyable.cpp
noncopyable.cpp: In function 'int main(int, char**)':
noncopyable.cpp:2: error: 'Foo::Foo(const Foo&)' is private
noncopyable.cpp:14: error: within this context
[jsalmon@river junk]$ gcc -DEXPLICIT_TEMPORARY noncopyable.cpp
[jsalmon@river junk]$ a.out
[jsalmon@river junk]$

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Siddharth Jain <siddharthjain.in@gmail.com>
Date: Sun, 12 Aug 2007 10:15:17 CST
Raw View
On Aug 12, 7:47 am, John Salmon <jsal...@thesalmons.org> wrote:

> <snip>
> class Foo {
>    Foo(const Foo& f);
> public:
>    Foo() {}
>
> };
>
> void
> func( const Foo& foo){
>
> }
>
> int
> main(int argc, char **argv){
> #ifndef EXPLICIT_TEMPORARY
>    func(Foo());
> #else
>    Foo f;
>    func(f);
> #endif
>    return 0;}
>
> </snip>
>
> Gcc (4.1.1) says:
>
> [jsalmon@river junk]$ gcc noncopyable.cpp
> noncopyable.cpp: In function 'int main(int, char**)':
> noncopyable.cpp:2: error: 'Foo::Foo(const Foo&)' is private
> noncopyable.cpp:14: error: within this context
> [jsalmon@river junk]$ gcc -DEXPLICIT_TEMPORARY noncopyable.cpp
> [jsalmon@river junk]$ a.out
> [jsalmon@river junk]$


TC++PL page no 98 says that:
In case of initializer for a const T& :
1  first, implicit type conversion to T is applied if necessary.
2. then, the resulting value is placed in a temporary variable of type
T; and
3. finally, this temporary variable is used as the value of the
initializer.

(eg in case of :     const double& cdr=1;
       it is actually
                            double tmp = double(1);
                            const double& cdr = tmp;

creating this temporary would require a public copy constructor, that
is why gcc is asking for a copy constructor when explicit temporary is
not used.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: john.salmon@gmail.com
Date: Sun, 12 Aug 2007 13:14:22 CST
Raw View
On Aug 12, 12:15 pm, Siddharth Jain <siddharthjain...@gmail.com>
wrote:
> On Aug 12, 7:47 am, John Salmon <jsal...@thesalmons.org> wrote:
>
>
>
> > <snip>
> > class Foo {
> >    Foo(const Foo& f);
> > public:
> >    Foo() {}
>
> > };
>
> > void
> > func( const Foo& foo){
>
> > }
>
> > int
> > main(int argc, char **argv){
> > #ifndef EXPLICIT_TEMPORARY
> >    func(Foo());
> > #else
> >    Foo f;
> >    func(f);
> > #endif
> >    return 0;}
>
> > </snip>
>
> > Gcc (4.1.1) says:
>
> > [jsalmon@river junk]$ gcc noncopyable.cpp
> > noncopyable.cpp: In function 'int main(int, char**)':
> > noncopyable.cpp:2: error: 'Foo::Foo(const Foo&)' is private
> > noncopyable.cpp:14: error: within this context
> > [jsalmon@river junk]$ gcc -DEXPLICIT_TEMPORARY noncopyable.cpp
> > [jsalmon@river junk]$ a.out
> > [jsalmon@river junk]$
>
> TC++PL page no 98 says that:
> In case of initializer for a const T& :
> 1  first, implicit type conversion to T is applied if necessary.
> 2. then, the resulting value is placed in a temporary variable of type
> T; and
> 3. finally, this temporary variable is used as the value of the
> initializer.
>
> (eg in case of :     const double& cdr=1;
>        it is actually
>                             double tmp = double(1);
>                             const double& cdr = tmp;
>
> creating this temporary would require a public copy constructor, that
> is why gcc is asking for a copy constructor when explicit temporary is
> not used.
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-...@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html                     ]

You're right to observe that the problem is related to const reference
initialization.
The function call is unnecessary baggage.

Also, it seems that Comeau complains if I turn off C++0x extensions.

But I am still confused.  In the following code, how is the
initialization of g
different from the initialization of h, and what changes in C++0x to
make the
initialization of h acceptable?

class Foo {
    Foo(const Foo& f);
public:
    Foo(){}
};

int
main(int argc, char **argv){
    Foo f;      // ok, default ctor
    const Foo &g(f); // ok
    const Foo &h((Foo())); // fails g++, Comeau without C++0x
extensions
    return &g!=&h;
}

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Sun, 12 Aug 2007 13:34:51 CST
Raw View
On Aug 12, 4:47 am, John Salmon <jsal...@thesalmons.org> wrote:
> I've got a class with a private copy constructor
> that I'd like to pass as a reference argument to a
> function.

> Gcc is unhappy with the following code unless I create an explicit
> temporary.  Comeau's online compiler seems to think it's fine.  It
> looks OK to me, too.  Since the argument to func() is a reference to
> Foo, there's no need for the compiler to copy-construct a temporary.
> Or is there?  Is gcc correct to complain?  Or is comeau correct to
> accept this?

The current version of the standard says that g++ is correct in
rejecting it.  I think that the current draft has been changed
to allow this, however.

--
James Kanze (GABI Software)             email:james.ka...@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


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]