I just realized this code compiles fine, but has undefined behavior and (naturally) crashes at runtime:
#include <map>
#include <memory>
#include <utility>
int main(int argc, char *argv[])
{
std::pair<std::unique_ptr<int>, int> a(&argc, 0);
std::map<std::unique_ptr<int>, int> m; m.insert(std::make_pair(&argc, argc));
}
This was a bit of a shocker for me because I just naturally assumed the explicit
nature of std::unique_ptr<T>
's T*
constructor would prevent me from converting a T *
to std::unique_ptr<T>
by accident, but it appears this safeguard no longer functions inside some wrappers that forward to constructors, like std::pair
.
So I guess I'm wondering a few things:
Is there a good mitigation for this? Is this a well-known problem?
Are these intentional, or should they be seen as defects in the standard?
If it's a defect, what is the correction that should be made? Can it be made at the library level, or does it require a language change? (e.g., does it require overloadability by
explicit
-ness?)
Bear in mind std::unique_ptr<int>
is just an example; it's not always obvious that the code is wrong, and it rapidly becomes more and more difficult to anticipate potentially dangerous conversions the more the code is templated, so I'm really wondering how people deal with this.