Как компилятор использует T ::operator< в std::set, когда параметр шаблона запрашивает std::less?

#c

#c

Вопрос:

При создании std::set одним из параметров шаблона является class Compare , значение которого по умолчанию равно std::less<T> .

Теперь, даже если вы не указываете специализацию std::less<T> , определение T::operator< достаточно хорошо для C , чтобы «разобраться». Но C ничего не выясняет, компилятор.

И компилятор выполняет ряд, я уверен, простых шагов. Что это за шаги?

Комментарии:

1. But C isn't figuring anything out, a compiler is. Справедливости ради, C диктует, что делает компилятор (до некоторой степени. Это определяет границы, которым должен следовать компилятор. В редких случаях это позволяет компилятору выбирать, что делать, но, похоже, это не один из таких случаев).

Ответ №1:

Стандартная библиотека определена таким образом, что std::less<T> будет использоваться operator< , если не предусмотрено иное. Итак, если вы не предоставляете специализацию, если тип поддерживает < , тогда это сработает.

От std::less<T> :

Объект функции для выполнения сравнений. Если не специализирован, вызывает operator< по типу T .

И для std::less<T>::operator() :

Возможная реализация :

 constexpr bool operator()(const T amp;lhs, const T amp;rhs) const
{
    return lhs < rhs;
}
  

Ответ №2:

Проверьте определяемую компилятором специализацию std::less<void>.

Как вы можете видеть, он просто возвращает результат lhs < rhs.

Что касается того, как компилятор знает, что нужно привязывать std::less<void> вместо std::less<T> , это потому, что никакая специализация std::less<T> не была явно написана. Поэтому, когда вы запрашиваете его, он должен быть сгенерирован автоматически.

Итак, почему компилятор находит std::less<void> вместо std::less<> ? Это потому, что, когда вы не передаете параметр шаблона, std::less вы получаете std::less<void> .

Комментарии:

1. std::less<T> определенно «существует», поскольку эта специализация автоматически генерируется, когда вы запрашиваете ее. std::less просто объявляется template<typename T = void> struct less; , поэтому, если вы запрашиваете std::less<> без указания T , вы получаете T = void по умолчанию. Единственная магия в том, что если T это тип указателя.

2. Я не уверен, почему вы ввели void в это.

3. Это то, что я понимаю из того, что я только что узнал от Google. Пожалуйста! Я был бы рад, если бы вы дали мне лучший ответ.

4. std::less<void> реализация не имеет значения, std::set<T> по умолчанию std::less<T>

5. @AriSweedler Да. Если вы предоставите, MyClass::operator< то std::less<MyClass> можете использовать общую реализацию std::less<T> , потому что для этой реализации просто требуется, чтобы существовал operator< который использует T . Обратите внимание, что вы также можете предоставить бесплатную функцию bool operator<(const MyClass amp;, const MyClass amp;) вместо этого, и она также будет работать.