The most paranoid way is
::new ((void *)::std::addressof(storage)) T(a, b, c);
Explanation:
::std::addressofguards against overloaded unaryoperator&onstorage, which is technically allowed by the standard. (Though no sane implementation would do it.) The::stdguards against any non-top-level namespaces (or classes) calledstdthat might be in scope.(void *)(which in this case is the equivalent of astatic_cast) ensures that you call the placementoperator newtaking avoid *rather than something else likedecltype(storage) *.::newskips any class-specific placementoperator news, ensuring that the call goes to the global one.
Together, this guarantees that the call goes to the library placement operator new taking a void *, and that the T is constructed at where storage is.
In most sane programs, though,
new (&storage) T(a,b,c);
should be sufficient.