0

我正在尝试使用 MSVC 141 编译从铬源代码中获取的 PDFium。该代码是自定义分配器。可以看到自定义分配器可以用wchar_t实例化没问题。wchar_t 显然是算术。但是,将其传递到向量中会使静态断言失败。下面的代码给出了一个静态断言,我没想到:

#include <iostream>
#include <type_traits>
#include <vector>

template <typename T>
struct FxAllocAllocator {
public:
    static_assert(std::is_arithmetic<T>::value,
        "Only numeric types allowed in this partition");

    using value_type = T;
    using pointer = T*;
    using const_pointer = const T*;
    using reference = T&;
    using const_reference = const T&;
    using size_type = size_t;
    using difference_type = ptrdiff_t;

    template <typename U>
    struct rebind {
        using other = FxAllocAllocator<U>;
    };

    FxAllocAllocator() noexcept = default;
    FxAllocAllocator(const FxAllocAllocator& other) noexcept = default;
    ~FxAllocAllocator() = default;

    template <typename U>
    FxAllocAllocator(const FxAllocAllocator<U>& other) noexcept {}

    pointer address(reference x) const noexcept { return &x; }
    const_pointer address(const_reference x) const noexcept { return &x; }
    pointer allocate(size_type n, const void* hint = 0) {
        return static_cast<pointer>(FX_AllocOrDie(n, sizeof(value_type)));
    }
    void deallocate(pointer p, size_type n) { FX_Free(p); }
    size_type max_size() const noexcept {
        return std::numeric_limits<size_type>::max() / sizeof(value_type);
    }

    template <typename U, typename... Args>
    void construct(U* p, Args&&... args) {
        new (reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...);
    }

    template <typename U>
    void destroy(U* p) {
        p->~U();
    }

    // There's no state, so they are all the same,
    bool operator==(const FxAllocAllocator& that) { return true; }
    bool operator!=(const FxAllocAllocator& that) { return false; }
};

int main()
{
    std::cout << "wchar_t:           " << std::is_arithmetic<wchar_t>::value << '\n';

    FxAllocAllocator<uint8_t> success;
    std::vector<wchar_t, FxAllocAllocator<wchar_t>> fail;
}

这超出了我的能力范围。到目前为止,我的猜测是 MSVC 编译器的工作方式与 GCC 不同,或者我缺少编译器选项。我已经尝试过 MSVC 141 和 142。C++11 到 c++17。谁能向我解释为什么这不能编译?

4

1 回答 1

2

似乎 Visual Studio 调试运行时代码的析构函数中有一个部分std::vector假定迭代器调试。由于可能的版权问题,我无法在此处发布代码。

我的猜测是调试运行时期望分配器是库存的 Visual C++ 分配器,带有调试信息。如果我错了,有人会纠正我,但这static_assert就是指向的地方。

您可以做的只是构建发布模式,因为发布构建不会调用调试库代码。

但是,如果您希望轻松调试应用程序,您可以:

1)将迭代器级别设置为0(_ITERATOR_DEBUG_LEVEL预处理器符号应为0)并重建

或者

2)创建另一个配置(调用它Release With Debug)并复制相同的设置Release,除了应该关闭优化。

于 2020-04-06T19:44:47.103 回答