简体   繁体   English

专攻std :: make_shared

[英]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. 我有一个严格对齐要求的类型(由于使用了AVX操作),它大于平台默认对齐。

To make usage of this class simpler, I would like to specialize std::make_shared to always use a suitable allocator for this type. 为了使这个类的使用更简单,我想专门化std::make_shared以始终为此类型使用合适的分配器。

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? 它会按预期工作吗?

From N4140 [namespace.std]/1 (emphasis mine): 从N4140 [namespace.std] / 1(强调我的):

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. 如果C ++程序向命名空间std或命名空间std中的命名空间添加声明或定义,则它是未定义的,除非另有说明。 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. 只有当声明取决于用户定义的类型并且特化符合原始模板的标准库要求且未明确禁止时, 程序才可以将任何标准库模板的模板特化添加到命名空间std

Since you are adding a template specialization which depends on a user-defined type, this is a valid extension of the std namespace. 由于您要添加依赖于用户定义类型的模板特化,因此这是std命名空间的有效扩展。

However, as pointed out by @dyp, you can't partially specialize function templates. 但是,正如@dyp所指出的,您无法部分专门化功能模板。 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). 您最好的选择是显式指定X构造函数的参数(丢失完美转发),或者只写一个make_shared_x函数(失去一致性)。

This is what I ended up doing to get a generic solution that doesn't involve a lot of boilerplate: 这就是我最终要做的事情,以获得一个不涉及大量样板的通用解决方案:

namespace xtd{
    template< typename T, std::size_t align = std::alignment_of<T>::value, typename... Args >
    std::shared_ptr<T> make_shared(Args&&... args){
        // Platform specific knowledge.
#if defined(_WIN64) || defined(_WIN32)
#if defined(_WIN64)
        const std::size_t default_alignment = 16;
#else
        const std::size_t default_alignment = 8;
#endif
#else
#error "Only windows for now"
#endif

        if (align > default_alignment) {
            typedef aligned_allocator<T, align> alloc_type;
            return std::allocate_shared<T, alloc_type>(alloc_type(), std::forward<Args>(args)...);
        }
        else {
            return std::make_shared<T>(std::forward<Args>(args)...);
        }
    }
}

Then I find Search & Replace std::make_shared with xtd::make_shared :) 然后我找到搜索和替换std::make_sharedxtd::make_shared :)

I wish this would be in the standard... 我希望这会符合标准......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM