struct Thing
{
Thing (Foo& p_f) : f (p_f) {}
Foo& f;
};
// Bar has an implicit conversion to a Foo
Bar b;
Thing t (b);
void Function (t);
C++ hidden reference traps
What I mean by a 'reference trap':
Because of the implicit conversion, a temporary object, of type Foo is created when 'b' is passed to the constructor of 't'. But when the constructor for 't' is finished, the temp Foo object is destroyed. By the time 'Function' is called with 't', the Foo object 't.f' is referencing is long gone.
Is there any chance of compilers ever being able to catch these types of bugs? I've found it to be pretty nasty because Debug builds appear to frequently survive unscathed, while Release builds crash (Turning on debug information in Release helps out fine, granted).
Actually, a temporary variable may only be passed by const reference, so your example shouldn't compile.
As for compilers being able to catch this sort of thing, not really. They would need to know whether the function called makes a copy or uses a reference, which is impossible if the definition of the function is unavailable. A warning is definitely possible in the other cases, though.
As for compilers being able to catch this sort of thing, not really. They would need to know whether the function called makes a copy or uses a reference, which is impossible if the definition of the function is unavailable. A warning is definitely possible in the other cases, though.
Yeah, I do try to avoid implicit conversions most of the time. They're constantly whispering 'convenience!' into my ears however, and sometimes I relent. BTW, do I get bonus points for const_cast? :)
Actual code:
Because 'InitialisingFactory1' is just a temporary transportation (i.e. always on the stack) for constructor parameters, I thought I'd get away with a bit of hackery. Or foolishness, take you pick. :)
I guess the fundamental question is: Is there a better way?
Actual code:
template <typename Type, typename Initialiser1>class InitialisingFactory1 // : Factory<Type>{ public: InitialisingFactory1 (Initialiser1& p_init1) : init1 (p_init1) {} InitialisingFactory1 (const Initialiser1& p_init1) : init1 (const_cast<Initialiser1&> (p_init1)) {} virtual Type* operator() (void* address) { return new (address) Type (init1); } Initialiser1& init1;};// InitialisingFactory2/3/4 for more params
Because 'InitialisingFactory1' is just a temporary transportation (i.e. always on the stack) for constructor parameters, I thought I'd get away with a bit of hackery. Or foolishness, take you pick. :)
I guess the fundamental question is: Is there a better way?
Well, yes, there is a better way. Don't implement a constructor from a const argument at all, because you can't.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement