В C ++ 14 ассоциативные контейнеры, похоже, изменились с C ++ 11 - [associative.reqmts] / 13 говорит:
Шаблоны функций - членов
find
,count
,lower_bound
,upper_bound
, иequal_range
не должен участвовать в разрешении перегрузки , если типCompare::is_transparent
не существует.
Какова цель сделать компаратор «прозрачным»?
C ++ 14 также предоставляет такие шаблоны библиотек:
template <class T = void> struct less {
constexpr bool operator()(const T& x, const T& y) const;
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
template <> struct less<void> {
template <class T, class U> auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) < std::forward<U>(u));
typedef *unspecified* is_transparent;
};
Так, например, std::set<T, std::less<T>>
было бы не иметь прозрачный компаратор, но std::set<T, std::less<>>
будет иметь один.
Какую проблему это решает и меняет ли это принцип работы стандартных контейнеров? Например, параметры шаблона std::set
по - прежнему Key, Compare = std::less<Key>, ...
, так же набор по умолчанию потеряет find
, count
и т.д. член?
Ответы:
См ответ Дитмар в и ответ remyabel в .
Нет, не по умолчанию.
Новые перегрузки шаблонов функций-членов
find
и т. Д. Позволяют использовать тип, сопоставимый с ключом контейнера, вместо использования самого типа ключа. См. N3465 Хоакина Му Лопеса Муньоса для обоснования и подробного, тщательно написанного предложения по добавлению этой функции.На встрече в Бристоле LWG согласилась, что функция гетерогенного поиска полезна и желательна, но мы не могли быть уверены, что предложение Хоакина будет безопасным во всех случаях. Предложение N3465 вызвало бы серьезные проблемы для некоторых программ (см. Раздел « Влияние на существующий код »). Хоакин подготовил обновленный черновой вариант предложения с некоторыми альтернативными реализациями с разными компромиссами, что было очень полезно, помогая LWG понять плюсы и минусы, но все они рисковали каким-то образом нарушить некоторые программы, поэтому не было единого мнения о добавлении этой функции. Мы решили, что, хотя добавлять эту функцию безоговорочно было бы небезопасно, было бы безопасно, если бы она была отключена по умолчанию и была только «включаться».
Ключевым отличием предложения N3657 (которое было доработкой в последнюю минуту мной и STL на основе N3465 и более позднего неопубликованного проекта Хоакина) было добавление
is_transparent
типа в качестве протокола, который можно использовать для выбора новой функциональности.Если вы не используете «прозрачный функтор» (т.е. тот, который определяет
is_transparent
тип), тогда контейнеры будут вести себя так же, как и всегда, и это по-прежнему по умолчанию.Если вы решите использовать
std::less<>
(что является новым для C ++ 14) или другой тип «прозрачного функтора», вы получите новую функциональность.Использование
std::less<>
легко с помощью шаблонов псевдонимов:Название
is_transparent
происходит от STL N3421, который добавил «алмазные операторы» в C ++ 14. «Прозрачный функтор» - это тот, который принимает любые типы аргументов (которые не обязательно должны быть одинаковыми) и просто перенаправляет эти аргументы другому оператору. Такой функтор оказывается именно тем, что вам нужно для гетерогенного поиска в ассоциативных контейнерах, поэтому этот типis_transparent
был добавлен ко всем операторам ромба и использовался как тип тега, чтобы указать, что новые функции должны быть включены в ассоциативных контейнерах. Технически контейнерам не нужен «прозрачный функтор», только тот, который поддерживает его вызов с разнородными типами (например,pointer_comp
тип в https://stackoverflow.com/a/18940595/981959 не является прозрачным согласно определению STL,pointer_comp::is_transparent
позволяет использовать его для решения проблемы). Если вы когда-либо выполняете поиск толькоstd::set<T, C>
с ключами типаT
илиint
тогдаC
нужно вызывать только аргументы типаT
иint
(в любом порядке), это не обязательно должно быть действительно прозрачным. Мы использовали это имя отчасти потому, что не смогли придумать лучшего имени (я бы предпочел,is_polymorphic
потому что такие функторы используют статический полиморфизм, но уже естьstd::is_polymorphic
характеристика типа, которая относится к динамическому полиморфизму).источник
<>
в связанном предложении, но это предложение не вводило<>
- это существующий синтаксис для пустого списка параметров шаблона. "Функторы алмазных операторов" были бы немного менее запутанными.В C ++ 11 есть не шаблоны членов
find()
,lower_bound()
и т.д. То есть, ничего не теряется этим изменением. Шаблоны элементов были введены в n3657, чтобы можно было использовать гетерогенные ключи с ассоциативными контейнерами. Я не вижу конкретного примера, где это было бы полезно, кроме хороших и плохих примеров!is_transparent
Использование предназначено , чтобы избежать нежелательных переходов. Если бы шаблоны элементов были неограниченными, существующий код мог бы напрямую проходить через объекты, которые были бы преобразованы без шаблонов элементов. Пример использования n3657 - это поиск объекта в astd::set<std::string>
с помощью строкового литерала: с определением C ++ 11std::string
объект создается при передаче строковых литералов соответствующей функции-члену. С изменением можно напрямую использовать строковый литерал. Если базовый объект функции сравнения реализован исключительно в терминахstd::string
, это плохо, потому что теперь a и строковый литерал, это может избежать создания временного объекта.std::string
будет создаваться для каждого сравнения. С другой стороны, если базовый объект функции сравнения может приниматьstd::string
Вложенный
is_transparent
тип в объекте функции сравнения предоставляет способ указать, следует ли использовать шаблонную функцию-член: если объект функции сравнения может работать с разнородными аргументами, он определяет этот тип, чтобы указать, что он может эффективно работать с различными аргументами. Например, новые объекты операторной функции просто делегируютсяoperator<()
и утверждают, что они прозрачны. Тот, по крайней мере, работает дляstd::string
тех , у кого перегрузок меньше, чем операторов, принимающих вchar const*
качестве аргумента. Поскольку эти функциональные объекты также являются новыми, даже если они делают неправильную вещь (например, требуют преобразования для какого-то типа), это, по крайней мере, не будет тихим изменением, приводящим к снижению производительности.источник
is_transparent
оно определено в объекте функции сравнения в соответствии с пунктом 13 раздела 23.2.4 [associative.reqmts]. Объекты функции сравнения по умолчаниюstd::less<Key>
соответствуют 23.4.2 [associative.map.syn] и 23.4. 3 [associative.set.syn]. Согласно 20.10.5 [сравнение] пункта 4 общий шаблон дляstd::less<...>
ничего не определить вложенный тип ,is_transparent
ноstd::less<void>
специализация делает. То есть нет, по умолчанию вы не получаете прозрачный оператор.is_transparent
?Далее следует вся копипаста от n3657 .
Процитировать Якка ,
и n3657,
n3421 представляет собой пример «прозрачных операторных функторов» .
Полный код здесь .
источник
std::set<std::string>
польза от «прохожденияchar const *
через», или вам нужно сделать этоstd::set<std::string, std::less<>>
?With the change proposed by N3465 the std::set::find() function would be an unconstrained template which would pass the const char* through to the comparator function, std::less<std::string>, which would construct a std::string temporary for every comparison. The LWG considered this performance problem to be a serious issue.
Стефан Т. Лававей рассказывает о проблемах, при которых компилятор продолжает создавать временные библиотеки, и о том, как его предложение прозрачных операторных функторов решит эту проблему в C ++ 1y.
GoingNative 2013 - Не помогайте компилятору (примерно на отметке часа)
источник