I have a couple of classes in which I need more control over member construction than is provided through initialization lists.
In one class, I need the ability to retry the construction of a member with different arguments if the original construction throws.
In a second class, I need to pass the address of the member object to another function which will in turn call the constructor (via placement new). The problem here is that the function is a black box and I don't know what it will pass to the constructor.
In both cases, it is a requirement that the member object is held in the containing object, not dynamically allocated.
What is the best way to accomplish this?
I noticed the question "Is it possible to defer member initialization to the constructor body?", which recommended boost::optional. This didn't quite solve my problem for a couple of reasons. First, I don't want to delay initialization, just have more control over it. Second, boost::optional stores an extra bool to indicate whether the object is initialized, which is not needed in my case. It did, however, get me thinking, and I came up with the solution I have posted below.
You cannot "retry" construction via a constructor alone. You can swallow/handle an exception caused within your constructor using try/catch, and continue to populate the object if code inside the constructor fails though (using simple assignments).
If your initialization list throws, you're... screwed? though - nothing in your initialization list should throw. It's executed prior to your constructor body and you have no control over exceptions thrown in it.
If you really need to retry construction with different parameters, wrap your construction in a factory function which can catch exceptions and try different options when they are received.
Moving on... when you call a constructor, you call a constructor. The constructor itself creates the object on the heap or on the stack based on whether or not you used dynamic allocation mechanisms (mainly new). You cannot decide within a constructor body itself to declare the object somewhere else, the decision has already been made. You'll have to directly use placement new when you call new in order to achieve that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With