Search code examples
c++c++14memory-alignmentstandard-library

Specializing std::make_shared


I have a type with a strict alignment requirement (due to AVX operations being used) that is larger than the platforms default alignment.

To make usage of this class simpler, I would like to specialize std::make_shared to always use a suitable allocator for this type.

Something like this:

namespace std{
    template<class... Args> inline
    auto make_shared<X, Args...>(Args&&... args){
        return std::allocate_shared(allocator_type<X, 32>, std::forward<Args>(args)...);
    }
}

My question is, is this allowed by the standard? Will it work as expected?


Solution

  • From N4140 [namespace.std]/1 (emphasis mine):

    The behavior of a C++program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

    Since you are adding a template specialization which depends on a user-defined type, this is a valid extension of the std namespace.

    However, as pointed out by @dyp, you can't partially specialize function templates. Your best options would be to explicitly specify the arguments to the X constructor (losing out on perfect-forwarding), or just write a make_shared_x function (losing out on consistency).