Указатели на элементы данных как ключи ассоциативного контейнера
Я пытаюсь создать
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 для указателей членов на всех трех.