Given a function which returns a heavy-to-construct and heavy-to-destroy object, is there a way to skip object construction and destruction if the function return value is not consumed?
HeavyObject func();
auto res = func(); // heavy object is constructed and returned
func(); // lightweight "null" object is returned and immediately destroyed
Is there a technique which I can use except tag dispatching like void func(NotConsumed);?
Update
It is okay to discard the return value, so [[nodiscard]] is not an option. Clients can decide if they want to use the result or not.
Let's assume func() initiates some job and HeavyObject serves as a some sort of handle. Clients can use it later to control/monitor the job, if they want to. Construction of such handle could involve e.g. creating pipes or heap memory allocation.
There are other overloads of func() where the return value must be consumed and which are marked as [[nodiscard]]. The new overload does not have this requirement but must be compatible with existing API.
Since C++17 there is the nodiscard attribute. However, this will only help to not ignore the returned value and the compiler is only encouraged to issue a warning.
I don't think there is a simple answer for what you want (ie no second function or overload). Also because the construction of the heavy object takes place already inside the function, not after it returned.
What you can do is to return a proxy that only when needed constructs the heavy object. Something along the line of :
struct heavy_object { int x; };
struct proxy {
int parameter_needed_to_construct_heavy_object;
operator heavy_object() {
return {parameter_needed_to_construct_heavy_object};
}
};
proxy func() {
return {42};
}
int main() {
func(); // ok, no heavy object is constructed
heavy_object ho = func(); // ok, heavy object is constructed
auto x = func(); // "ok-ish", caller must be aware that x is just the proxy
}
Instead of an implicit converions a get() could take its place, but that wont change the fact that the caller must do something extra to get the actual return value.
Having said that, I think using two seperate functions or an overload as you propse is the simpler and cleaner solution.
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