Reputation: 28538
Is it possible to tell g++ to use the FOO&
operator when constructing the FOO object ?
struct FOO {
FOO( FOO & foo ) { // non-const copy constructor
}
operator FOO&() {
return *this;
}
FOO( int i ) {
}
};
int main() {
FOO a(FOO(5));
}
I currently get the following error:
In function int main():
error: no matching function for call to FOO::FOO(FOO)
note: candidates are: FOO::FOO(int)
note: FOO::FOO(FOO&)
-- edit --
Note that I try to setup an object that can exchange the ownership of a resource.
Calling FOO foo1(foo)
make foo to lose the ownership of the resource, this mean that foo cannot be const
.
Also note that I want to avoid smart-pointer mechanism.
Upvotes: 1
Views: 480
Reputation: 131907
Your conversion operator will never be picked up.
§12.3.2 [class.conv.fct] p1
A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to (possibly cv-qualified) void.
The reason is that the conversions mentioned here (except to cv void
) are already done by so-called standard conversions (qualification conversion (adding const
or volatile
) and identity conversion (binding an object to a reference)) and standard conversions are always preferred to user-defined conversions:
§13.3.3.2 [over.ics.rank] p2
a standard conversion sequence (13.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence [...]
For your specific case, if you want to transfer ownership, do so in C++11 style, with a move constructor.
#include <utility> // move
struct foo{
int resource;
foo(int r)
: resource(r) {}
foo(foo&& other)
: resource(other.resource)
{ other.resource = 0; }
};
int main(){
foo f1(foo(5));
//foo f2(f1); // error
foo f3(std::move(f1)); // OK
}
Transferring ownership via non-const copy constructors is a very bad idea, as such a type can never be stored in standard containers, see the ugly std::auto_ptr
(replaced by std::unique_ptr
in C++11, which has proper move semantics).
Upvotes: 3
Reputation: 42845
Note that I try to setup an object that can exchange the ownership of a resource.
Calling FOO foo1(foo) make foo to lose the ownership of the resource, this mean that foo cannot be const.
Also note that I want to avoid smart-pointer mechanism.
So you've got something like:
struct FOO {
// ...
SomeType* storage;
bool owns_storage;
// ...
FOO(const FOO& foo): storage(foo.storage), owns_storage(true) {
foo.owns_storage = false; /* <-- fails to build */ }
~FOO() { if(owns_storage) delete storage; }
};
And you need a copy to set owns_storage
to false
on the const
original object. Use the mutable
keyword and your problem goes away:
struct FOO {
// ...
SomeType* storage;
mutable bool owns_storage;
// ...
FOO(const FOO& foo): storage(foo.storage), owns_storage(true) {
foo.owns_storage = false; /* builds fine now */ }
~FOO() { if(owns_storage) delete storage; }
};
Upvotes: 1