You need to enable JavaScript to run this app. std::pmr::polymorphic_allocator类型错误为何未被编译期检测到
优惠活动
大模型
产品
解决方案
定价
更多

std::pmr::polymorphic_allocator类型错误为何未被编译期检测到

pmr::polymorphic_allocator类型不匹配无法编译期检测问题

我在开发中发现,pmr::polymorphic_allocator类型不匹配的问题似乎无法在编译期被正常检测到。

我定义了一个示例类MyClass,其使用pmr::polymorphic_allocator作为构造函数入参,代码如下:

// file MyClass.hpp
#include <memory_resource>

class Item
{
    // class members...
};

class MyClass
{
public:
    explicit MyClass(std::pmr::polymorphic_allocator<Item> allocator)
    {
        // ....
    }

    // other members
};

随后我编写如下代码测试该类的使用:

#include "MyClass.hpp"
#include <memory_resource>

// 符合预期,该行编译无报错
auto myClass1 = MyClass(std::pmr::polymorphic_allocator<Item>());

// 不符合预期,该行同样编译无报错
auto myClass2 = MyClass(std::pmr::polymorphic_allocator<OtherType>());

其中OtherType是和Item完全无关的类型。

为了检测类型不匹配的问题,我在MyClass的构造函数中添加了静态类型校验,代码如下:

// file MyClass.hpp
#include <memory_resource>
#include <type_traits>

class Item
{
    // class members...
};

class MyClass
{
public:
    explicit MyClass(std::pmr::polymorphic_allocator<Item> allocator)
    {
        static_assert(std::is_same<Item, decltype(allocator)::value_type>::value,
            "Improper allocator!"); 
        // ....
    }

    // other members
};

但添加校验后,类型不匹配的问题仍然未被编译期检测到。我使用的开发环境为GCC 10.2.0、CLion 2021.1。


问题原因

pmr::polymorphic_allocator提供了转换构造函数,会隐式转换为符合入参要求的分配器类型。它的核心逻辑是类型擦除的底层std::pmr::memory_resource指针,和分配器的value_type无关,因此polymorphic_allocator<OtherType>会被编译器自动隐式转换为polymorphic_allocator<Item>,构造函数拿到的入参allocator的value_type已经是Item,所以你写的static_assert永远不会触发。

解决方案

如果需要禁止传入其他类型的polymorphic_allocator,可以改用模板构造函数加类型约束的写法,在隐式转换发生前拦截错误类型:

#include <memory_resource>
#include <type_traits>

class Item
{
    // class members...
};

class MyClass
{
public:
    template<typename T>
    explicit MyClass(std::pmr::polymorphic_allocator<T> allocator)
    {
        static_assert(std::is_same_v<T, Item>, "Improper allocator! Allocator value_type must be Item");
        // 其余初始化逻辑
    }

    // other members
};

这种写法下,传入polymorphic_allocator<OtherType>时模板参数T会被推导为OtherType,static_assert会直接触发编译报错,达到校验类型的效果。

内容的提问来源于stack exchange,提问作者VillageTech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.17 11:06:04