【问题标题】:Specializing std::make_shared专门化 std::make_shared
【发布时间】:2015-07-17 10:28:46
【问题描述】:

我的类型具有严格的对齐要求(由于使用了 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)...);
    }
}

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

【问题讨论】:

  • 你不能使用alignas
  • @dyp 不,或者是的,我已经这样做了,但由于this,它不适用于堆分配。这种专门化是为了在最常见的使用情况下甚至在堆上应用对齐。

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


【解决方案1】:

来自 N4140 [namespace.std]/1(重点是我的):

除非另有说明,否则如果 C++ 程序将声明或定义添加到命名空间 std 或命名空间 std 内的命名空间,则该 C++ 程序的行为是未定义的。 程序可以添加模板特化 仅当声明依赖于用户定义的类型并且特化满足原始模板的标准库要求并且未明确禁止时,任何标准库模板才能将 std 命名空间。

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

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

【讨论】:

  • 正是我想要的。我记得有这样做的规则,但不知道它是合法的确切条件。你觉得这样做有什么缺点吗?
  • @EmilyL。您不能部分特化函数模板,因此函数模板的每个特化都必须是完全(或显式)特化。因此,不能利用这个漏洞实现完美转发。 (您也不能将它一般用于类模板之类的一组类型。)
  • 哈,我刚刚在std 中看到了模板特化,并找到了这句话,忽略了部分函数模板特化。也许@EmilyL。最好只写一个make_shared_x 函数。
  • @TartanLlama 这是我目前的解决方案,但我希望有一些通用的东西,当人们使用 make_shared 并期望它能够工作时不会爆炸。
  • @Dyp 傻了我,我知道我不能部分专门化函数模板......但我责怪突然急性暂时失忆......我想我真的希望这个工作sigh
【解决方案2】:

这就是我最终为获得一个不涉及大量样板的通用解决方案所做的工作:

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 & Replace std::make_shared with xtd::make_shared :)

我希望这是标准...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-05
    • 1970-01-01
    • 2019-04-18
    • 2017-10-09
    相关资源
    最近更新 更多