Reputation: 20570
Recently, I had a bug where, we changed the function from
void update_waypoint_heading(const double new_observation, waypoint)
{
// ....
waypoint.heading = default_heading_deg * waypoint.some_magic_number
}
// Call the function and the function will calculate new heading and mutate heading in waypoint
update_waypoint_heading(new_observation, waypoint);
to
double update_waypoint_heading(const double new_observation, waypoint)
{
// ....
return default_heading_deg * waypoint.some_magic_number
}
// Here the caller is supposed to be responsible for mutation
waypoint.heading = update_waypoint_heading(new_observation, waypoint);
We had a bug where we changed the function but did not change the caller. So we ended with
update_waypoint_heading(new_observation, waypoint);
Where update_waypoint_heading
started to return the new heading. But it never got set to the waypoint. This was also perfectly legal for the compiler.
Is it possible to declare a parameter as mutant
(like the opposite of const
), where it will throw a compiler error if it does not get mutated. So that I can catch these cases at compile time
Upvotes: 0
Views: 376
Reputation: 385144
No, and it wouldn't make much sense either.
You pass an argument into a function, and want a keyword to mandate that the calling scope then assigns the result of that function into some part of the same thing you passed as an argument?
This is very convoluted.
If a function returns a result that ought to be used, then that is documented by its return type. If it modifies its by-reference arguments, then that should also be documented. Do not switch from one to the other after you've already got code using that function!
HOWEVER! There is the nodiscard
attribute which will prevent the result of calling the function from simply being, well, discarded. That would have flagged this case up, and may be what you're really looking for.
You'll need a nice C++17 compiler to use it.
I still think this is a bit leaky, though. It's not up to your function to decide what the calling scope does with its result. Just don't change function semantics! Write a new function with a new name if you need to. "Update" is no longer a good descriptive name for what it does anyway.
Upvotes: 4