Сбой static_assert в сочетании с std :: vector с пользовательским распределителем - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь скомпилировать PDFium, взятый из исходного кода хрома, с помощью MSV C 141. Код является специальным распределителем. Вы можете видеть, что пользовательский распределитель может быть создан с помощью wchar_t без проблем. wchar_t - это, очевидно, арифметика c. Однако передача его в вектор не соответствует утверждениям c. Следующий код дает утверждение о состоянии c, которого я не ожидаю:

#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;
}

Это не в моих силах, чтобы понять. Я думаю, что компилятор MSV C работает не так, как G CC, или мне не хватает опции компилятора. Я пробовал MSV C 141 и 142. C ++ 11 до C ++ 17. Может кто-нибудь объяснить, почему это не компилируется?

1 Ответ

2 голосов
/ 06 апреля 2020

Кажется, что в коде среды отладки Visual Studio есть раздел в деструкторе std::vector, который предполагает отладку итератора. Я не могу опубликовать код здесь из-за возможных проблем с авторским правом.

Я предполагаю, что среда выполнения отладки ожидает, что распределители будут стандартными распределителями Visual C ++ с отладочной информацией. Кто-то исправит меня, если я ошибаюсь, но на это указывает static_assert.

Что вы можете сделать, это только построить режим Release, так как сборка Release не вызывает код библиотеки отладки ,

Однако, если вы хотите легко отладить приложение, вы можете:

1) Установить уровень итератора равным 0 (_ITERATOR_DEBUG_LEVEL символ препроцессора должен быть равен 0) и перестроить

или

2) Создайте другую конфигурацию (назовите ее Release With Debug) и скопируйте те же настройки для Release, за исключением того, что оптимизации следует отключить.

...