The C++ program (somewhat unexpectedly, at first, to me) compiles and runs fine, except for the line commented at the end of main()
, which is a compile-time error if it is uncommented.
#include <typeinfo>
#include <iostream>
struct Foo {
int x;
};
template <typename T>
void create(char *buffer)
{
std::cout << "creating " << typeid(T).name() << std::endl;
new (buffer) T();
}
template <typename T>
void destroy(char *buffer)
{
std::cout << "destroying " << typeid(T).name() << std::endl;
((T*)buffer)->~T();
}
int main(int argc, char **argv)
{
char buffer[sizeof(Foo) > sizeof(bool) ? sizeof(Foo) : sizeof(bool)];
// create/destroy Foo via template function calls
create<Foo>(buffer);
destroy<Foo>(buffer);
// now do the above explicitly...
new (buffer) Foo();
((Foo*)buffer)->~Foo();
// create/destroy bool via template function calls
create<bool>(buffer);
destroy<bool>(buffer);
// now do the above explicitly...
new (buffer) bool();
// ((bool*)buffer)->~bool(); // oops, doesn't work
return 0;
}
I gather from this that C++ (or at least g++'s idea of C++) allows an "explicit destructor call" of a template parameter type, even when manually doing the type replacement oneself results in a syntax error (since bool
doesn't really actually have a destructor to call).
To be more explicit, the line:
((T*)buffer)->~T();
compiles and runs fine when T is instatiated on a bool
, but doing the same thing with an actual bool
:
((bool*)buffer)->~bool();
is a syntax error.
I'm discovered this behavior as I was doing template metaprogramming and find it a very helpful, so I'm guessing it's standard and was added specifically to handle cases like the one I have above. Does anyone know for sure if this is actually the case, and when this behavior was standardized if it is?
In addition, can anyone point to what the exact wording in the standard is that allows this, and the scope of the situations it allows? (I'm not adept at reading standardese so I have a hard time figuring this out myself.)