I just stumbled into a cast from a smart pointer and wanted to check if static_cast
could assert at compile time that the following is nonsensical:
int main()
{
char foobar[4] = "Foo";
std::unique_ptr<char[]> myptr = static_cast<decltype(myptr)>(foobar);
myptr.reset();
return 0;
}
What happens here is that myptr
attempts to free foobar
.
I am not asking what a smart pointer is or how to allocate or otherwise fix the above.
I thought this problem should be caught at compile time, since these types should be completely incompatible.
Why is this not detected at compile time?
The static_cast
causes a call to the constructor of std::unique_ptr
similar to what you can see in the following example
#include <iostream>
#include <memory>
using std::cout;
using std::endl;
class Something {
public:
explicit Something(int) {
cout << __PRETTY_FUNCTION__ << endl;
}
};
int main() {
auto something = static_cast<Something>(1);
(void) something;
}
If you are wondering why the static_cast
causes a call to the constructor of std::unique_ptr
it can be explained with the following quote from the standard (emphasis mine)
Static cast [expr.static.cast/4]
An expression e can be explicitly converted to a type
T
using astatic_cast
of the formstatic_cast<T>(e)
if the declarationT t(e);
is well-formed, for some invented temporary variablet
(8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The expressione
is used as a glvalue if and only if the initialization uses it as a lvalue.
So basically in your example the array is treated as a parameter to the constructor of unique_ptr
and then the imaginary temporary is then used to initialize the variable myptr
(with elision in most cases)
The constructor that is called in your example is (2) in the following cppreference page http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr
explicit unique_ptr( pointer p ) noexcept;
Here you get a unique_ptr
that points to the array.
Then when you call reset()
the unique_ptr
attempts to delete the variable with automatic lifetime and causes undefined behavior. This however is not required to be detected by the compiler.