Указатели на элементы данных как ключи ассоциативного контейнера

Я пытаюсь создать std::setуказателей на элементы данных . Однако я не могу найти метод для сортировки или хеширования таких указателей.

Их нельзя сравнивать с operator<, они, похоже, не поддерживаются, и нет стандартного целочисленного типа, который гарантированно содержал бы их представление (они могут не соответствовать std::uintptr_t).

Это то, что я попробовал сначала (https://godbolt.org/z/K8ajn3rM8):

      #include <set>

struct foo
{
    int x;
    int y;
};

using t_member_ptr = int (foo::*);

const std::set<t_member_ptr> members = {
    &foo::x,
    &foo::y
};

Выдает ошибку error: invalid operands of types 'int foo::* const' and 'int foo::* const' to binary 'operator<'. Полное сообщение об ошибке также подразумевает, что это происходит во время создания экземпляра std::less.

Я нашел аналогичный вопрос (Набор указателей на член), но он восходит к C++14, и ответы сводятся к тому, чтобы «поместить указатели в вектор и вместо этого выполнить линейный поиск».

Были ли какие-либо изменения в C++17 или C++20, которые позволяют использовать указатели на элементы данных в качестве ключей для стандартных ассоциативных контейнеров?

1 ответ

Сравните их побайтно, например, используя этот компаратор:

      #include <cstring>
#include <type_traits>

struct BitLess
{
    template <typename T>
    requires std::has_unique_object_representations_v<T>
    constexpr bool operator()(const T &a, const T &b) const
    {
        return std::memcmp(reinterpret_cast<const char *>(&a), reinterpret_cast<const char *>(&b), sizeof(T)) < 0;
    }
};

Проверка std::has_unique_object_representations_v<T>гарантирует, что внутри нет набивки. Он попробовал это на GCC, Clang и MSVC и вернул true для указателей членов на всех трех.

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