Допустим, меня волнует двоичный размер, я уже использую std::map, и мне нужен набор. Вместо std::set<T> я мог бы использовать std::map<T, bool>. Поможет ли это, или общий код уже используется под капотом?
Я сомневаюсь, что стандарт C++ что-то говорит о совместном использовании кода, поэтому в разных реализациях это может различаться, но я предполагаю, что существует некоторая общая практика.
std::map<T, bool> и std::map<T, V> в любом случае будут двумя разными классами. Также существует разница между общим кодом и общим скомпилированным кодом (например, std::less<T> будет общим, но, скорее всего, будет встроенным).
@ 463035818_is_not_an_ai Это в первом предложении.
@ 463035818_is_not_an_ai настоящая причина вопроса в том, что мне любопытно, надеюсь, это нормально.
@KonradRudolph первое предложение «Мне нужен набор». Я спрашиваю, зачем? почему? почему бы просто не использовать карту?
@ 463035818_is_not_an_ai Нет. Первое предложение: «… Меня волнует двоичный размер…». Это вполне разумная причина: это распространенный метод оптимизации размера кода, заключающийся в объединении общего кода шаблонов классов путем наследования ими общей базы с реализацией.
Ничего страшного. Просьба о разъяснениях часто ошибочно воспринимается как агрессия и отрицание, ничего подобного не предназначалось.
@KonradRudolph Я понял. Им не нужен набор, содержащий те же элементы, что и карта. Они используют карту, а в других местах им нужен набор. Это все в вопросе, и я мог бы прочитать более внимательно.
Шаблоны не используют общий код в конечном исполняемом файле. Шаблон — это просто рецепт создания кода для заданных параметров шаблона (обычно типов). Чтобы уменьшить размер исполняемого файла, лучше избегать использования шаблонов.





Это вещь, которую вам придется измерить и увидеть. Вы правы в том, что std::map<T, std::monostate> больше похоже на std::map<T, U>, чем на std::set<T>, поскольку основные сравнения должны проходить через value.first, а не напрямую value.
Кстати, основные реализации реализуют все ассоциативные контейнеры с одним шаблоном базового класса, а также все неупорядоченные ассоциативные контейнеры с одним шаблоном класса. Однако все это шаблоны, поэтому в результате этого будет разное количество повторного использования объектного кода.
Я провел быстрое измерение с помощью Visual Studio. Использование std::unordered_set<int> вместо std::unordered_map<int, std::monostate> (пока std::unordered_map<int, int> уже используется) добавило 1536 байт, что весьма незначительно. Поэтому я предполагаю, что вы правы и существует общий шаблон базового класса.
Как вы заметили, это зависит от реализации.
Тем не менее, да, по крайней мере, в некоторых широко используемых компиляторах (например, gcc) set и map используют общую реализацию.
Например, вот базовая реализация красного/черного дерева, которую gcc использует как для набора, так и для карты:
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_tree.h
Вот часть заголовка карты, где это используется:
typedef _Rb_tree<key_type, value_type, _Select1st<value_type>,
key_compare, _Pair_alloc_type> _Rep_type;
/// The actual tree structure.
_Rep_type _M_t;
Это детали реализации, и вам не следует на это полагаться.