专攻std :: make_shared

时间:2015-07-17 10:28:46

标签: c++ c++14 memory-alignment standard-library

我的类型具有严格的对齐要求(由于使用了AVX操作),该类型大于平台默认对齐。

为了使这个类的使用更简单,我想专门设置std::make_shared以始终为此类型使用合适的分配器。

这样的事情:

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)...);
    }
}

我的问题是,标准是否允许这样做?它会按预期工作吗?

2 个答案:

答案 0 :(得分:9)

来自N4140 [namespace.std] / 1(强调我的):

  

如果C ++程序向命名空间std或命名空间std中的命名空间添加声明或定义,则该行为是未定义的,除非另有说明。 程序可能会添加模板专业化   对于任何标准库模板到命名空间std,仅当声明取决于用户定义的类型且专业化符合原始模板的标准库要求且未明确禁止时。

由于您要添加依赖于用户定义类型的模板特化,因此这是std命名空间的有效扩展。

但是,正如@dyp所指出的,你不能部分专门化功能模板。您最好的选择是明确指定X构造函数的参数(丢失完美转发),或者只写一个make_shared_x函数(失去一致性)。

答案 1 :(得分:5)

这就是我最终要做的一个通用解决方案,它不涉及很多样板:

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)...);
        }
    }
}

然后我找到了Search&amp;将std::make_shared替换为xtd::make_shared:)

我希望这会符合标准......