Hello everyone,
I'm not entirely certain if this is the correct list, but here we go:
I have a question regarding c++, in particular passing a temporary object by reference into a constructor.
A small example which illustrates the issue is as follows:
// file class.h
#ifndef __CLASS_H #define __CLASS_H
#include <memory>
namespace CLS {
class Bar;
class Foo { public: typedef std::auto_ptr<const Bar> bar_pointer; private: bar_pointer m_bar; public: Foo(bar_pointer& bar); // non-const ref for ownership transfer ~Foo(void); bool check(void) const; };
class Bar { public: Bar(void); ~Bar(void); bool exists(void) const; };
class Group { private: Foo m_foo; public: Group(void); ~Group(void); bool check(void) const; };
}
#endif // __CLASS_H
// file class.cpp
#ifndef __CLASS_CPP #define __CLASS_CPP
#include "class.h"
namespace CLS {
#pragma mark Foo
Foo::Foo(Foo::bar_pointer& bar) : m_bar(bar) { }
Foo::~Foo(void) { }
bool Foo::check(void) const { if (m_bar.get()) return m_bar->exists(); return false; }
#pragma mark Bar
Bar::Bar(void) { }
Bar::~Bar(void) { }
bool Bar::exists(void) const { return true; }
#pragma mark Group
Group::Group(void) : m_foo(Foo::bar_pointer(new Bar())) { } // Compiler fails here -----------<<<<
Group::~Group(void) { }
bool Group::check(void) const { return m_foo.check(); }
}
#endif // __CLASS_CPP
Whatever the compiler I use (on the Mac) i get a compilation failure with the error:
No matching constructor for initialization of CLS::Foo Candidate constructor(the implicit copy constructor) not viable: no known conversion from Foo::bar_pointer to CLS::Foo
This seems really quite odd to me. I have managed to get code like this to compile, and run without issue using Visual Studio 2008 for quite some time. This is in itself no proof of correctness, but it really does seem that gcc is getting this wrong.
The problem disappears if I change the constructor in Foo to take the pointer by value, as in
Foo(bar_pointer bar);
But this would be sub-optimal, since pass-by-value should leave the argument unaltered, which would not be the case here.
I have tried GCC 4.0, 4.2, LLVM GCC 4.2 which all exhibit this same behaviour.
If GCC is correct, according to standard, then I would really appreciate, for my own edification, an explanation of what requires it to be so. In particular, what makes this different than default arguments passed by reference?
Thank you very much,
Jason
|