Чего не хватает моему распределителю, чтобы его можно было заменить

Я все еще изучаю распределители и боролся с ошибкой, которая возникает, например, при std::vector::shrink_to_fit() вызов метода. Вот мой распределитель (я пропустил некоторые (Я считаю) неважный код для краткости):

#include <cinttypes>
#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
#include <forward_list>
#include <array>
#include <map>

enum class MemoryBank : std::uint8_t
{
    General,
    Audio,
    Video
};

template<std::size_t ChunkSize = 1024>
class ChunkMemoryManager
{
public:
    ChunkMemoryManager() { std::cout << "ChunkMemoryManager()\n"; }
    char* allocate(std::size_t bytes)
    {
        return nullptr;
        /*skipped*/
    }

    void deallocate(char* address, size_t size)
    {
        /*skipped*/
    }

private: // types
    struct Chunk
    {
        Chunk() { freeSlots.emplace_front(0, ChunkSize); }

        std::array<char, ChunkSize>                            memory;
        std::forward_list<std::pair<std::size_t, std::size_t>> freeSlots;
    };

private: // data
    std::list<Chunk> chunks;
};

template<typename T, MemoryBank bank = MemoryBank::General, typename MemoryManager = ChunkMemoryManager<1024>>
class MemoryManagerAllocator
{
public:
    using value_type                  = T;
    using propagate_on_container_swap = std::true_type();
    
    template<typename U>
    struct rebind
    {
        using other = MemoryManagerAllocator<U, bank, MemoryManager>;
    };

    MemoryManagerAllocator()                                             = default;
    MemoryManagerAllocator(const MemoryManagerAllocator&)                = default;
    MemoryManagerAllocator& operator=(const MemoryManagerAllocator& rhs) = default;

    template<class U, MemoryBank UMemoryBank, typename UMemoryManager>
    constexpr MemoryManagerAllocator(const MemoryManagerAllocator<U, UMemoryBank, UMemoryManager>&) noexcept {};

    [[nodiscard]] T* allocate(std::size_t n) { return reinterpret_cast<T*>(memoryManager.allocate(n * sizeof(T))); }

    void deallocate(T* p, std::size_t n) noexcept
    {
        memoryManager.deallocate(reinterpret_cast<char*>(p), n * sizeof(T));
    }

private:
    inline static MemoryManager memoryManager;
};

template<class T, MemoryBank TMemoryBank, class TMemoryManager, class U, MemoryBank UMemoryBank, class UMemoryManager>
bool operator==(const MemoryManagerAllocator<T, TMemoryBank, TMemoryManager>&,
                const MemoryManagerAllocator<U, UMemoryBank, UMemoryManager>&)
{
    return true;
}

template<class T, MemoryBank TMemoryBank, class TMemoryManager, class U, MemoryBank UMemoryBank, class UMemoryManager>
bool operator!=(const MemoryManagerAllocator<T, TMemoryBank, TMemoryManager>&,
                const MemoryManagerAllocator<U, UMemoryBank, UMemoryManager>&)
{
    return false;
}

Код драйвера:

int main()
{
    using MMAllocator = MemoryManagerAllocator<int>;
    std::vector<int, MMAllocator> v;
    v.shrink_to_fit();
}

выдает следующую ошибку:

In file included from /usr/include/c++/13/cstdint:38,
                 from /usr/include/c++/13/cinttypes:38,
                 from /home/user/.vs/allocator/src/main.cpp:1:
/usr/include/c++/13/bits/stl_vector.h: In instantiation of ‘constexpr void std::vector<_Tp, _Alloc>::swap(std::vector<_Tp, _Alloc>&) [with _Tp = int; _Alloc = MemoryManagerAllocator<int>]’:
/usr/include/c++/13/bits/alloc_traits.h:908:28:   required from ‘static constexpr bool std::__shrink_to_fit_aux<_Tp, true>::_S_do_it(_Tp&) [with _Tp = std::vector<int, MemoryManagerAllocator<int> >]’
/usr/include/c++/13/bits/vector.tcc:721:56:   required from ‘constexpr bool std::vector<_Tp, _Alloc>::_M_shrink_to_fit() [with _Tp = int; _Alloc = MemoryManagerAllocator<int>]’
/usr/include/c++/13/bits/stl_vector.h:1069:9:   required from ‘constexpr void std::vector<_Tp, _Alloc>::shrink_to_fit() [with _Tp = int; _Alloc = MemoryManagerAllocator<int>]’
/home/user/.vs/allocator/src/main.cpp:143:20:   required from here
/usr/include/c++/13/bits/stl_vector.h:1589:9: error: ‘value’ is not a member of ‘std::allocator_traits<MemoryManagerAllocator<int> >::propagate_on_container_swap’ {aka ‘std::integral_constant<bool, true>()’}
 1589 |         __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value
      |         ^~~~~~~~~~~~~~~~
gmake[3]: *** [CMakeFiles/allocator.dir/build.make:76: CMakeFiles/allocator.dir/src/main.cpp.o] Error 1

Если я правильно понимаю, компилятор не может поменять мой распределитель, я прав? Как решить эту ошибку?

Обновление: я исправил код, чтобы он отображал упомянутую выше ошибку. Также я заметил, что этот код работает в MSVC и не работает с GCC.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эта строка неверна:

using propagate_on_container_swap = std::true_type();

Вы определяете свой propagate_on_container_swap как тип функции, который не принимает параметров и возвращает std::true_type.

Однако std::allocator_traits ожидает, что propagate_on_container_swap будет определен как тип класса/структуры, который имеет вложенный статический член value. std::true_type и std::false_type удовлетворяют этому требованию, например:

using propagate_on_container_swap = std::true_type;

Другие вопросы по теме