Подтвердить что ты не робот

Почему сами шаблоны STL шаблоны, а не их оператор вызова функции?

Функторы STL реализованы следующим образом:

template<class T>
struct less{
  bool operator()(T const& lhs, T const& rhs){
    return lhs < rhs;
  }
};

Это заставляет нас упоминать (возможно, длинный) тип каждый раз, когда мы создаем такой функтор. Почему они не реализованы, как показано ниже? Любые причины?

struct less{
  template<class T>
  bool operator()(T const& lhs, T const& rhs){
    return lhs < rhs;
  }
};

Это сделает их пригодными для использования без упоминания (возможно, длинных) типов.

4b9b3361

Ответ 1

Это также сделало бы невозможным специализировать их для пользовательских типов.

Они должны быть точкой настройки.


Подводя итоги обсуждениям в комментариях:

Хотя технически это возможно сделать, как предлагает Xeo, языковой стандарт не позволяет этого.

Очень сложно написать шаблон рабочего класса, если пользователям разрешено специализировать отдельные функции шаблона. В некоторых случаях может быть хорошей идеей специализировать весь класс для определенного пользователем типа.

Поэтому стандарт С++ 98 пишет (17.4.3.1):

Это означает, что программа С++ добавляет объявления или определения в пространство имен std или пространства имен в пространстве имен std, если не указано иное. Программа может добавлять специализированные шаблоны для любого шаблона стандартной библиотеки в пространство имен std.

Как не указано иначе, что код Xeo разрешен, мы должны понимать, что это не так. Возможно, не совсем очевидно! Или что "специализированные шаблоны" применяются только к классам.

Новый стандарт С++ 11 расширил эту часть и более подробно изложил ее (17.6.4.2):

Поведение программы на С++ undefined, если оно добавляет объявления или определения в пространство имен std или в пространство имен в пространстве имен std, если не указано иное. Программа может добавить специализацию шаблона для любого стандартного шаблона библиотеки в пространство имен std только в том случае, если объявление зависит от пользовательского типа, а специализация соответствует требованиям стандартной библиотеки для исходного шаблона и явно не указана запрещено.

Поведение программы на С++ undefined, если оно объявляет

- явная специализация любой функции-члена стандартного шаблона библиотеки библиотеки, или
 - явная специализация любого шаблона функции-члена стандартного класса библиотеки или шаблона класса, или
- явная или частичная специализация любого шаблона класса участника стандартного класса библиотеки или шаблона класса.

Программа может явно создавать шаблон, определенный в стандартной библиотеке, только если объявление зависит от имени определяемого пользователем типа, и экземпляр отвечает стандартным требованиям библиотеки для исходного шаблона.

Ответ 2

Может быть:

std::multiset<long, std::less<int> > moduloset;

Нечетная вещь, но дело в том, что std::less<int>, std::less<long>, std::less<unsigned int> реализуют различные математические функции, которые при передаче (результат преобразования) выражают определенные результаты. Различные алгоритмы и другие стандартные компоненты библиотеки работают, задавая функтор, поэтому для меня имеет смысл, что существуют разные функторы для представления этих разных математических функций, а не только разные перегрузки operator() на одном функторе.

Кроме того, функтор с шаблоном operator() не может быть адаптивным двоичным предикатом, поскольку он не имеет типов аргументов (аргумент может иметь любой тип). Поэтому, если std::less были определены так, как вы предполагаете, тогда он не мог участвовать в материалах в <functional>.

Кроме того, на весьма спекулятивной ноте - std::less, вероятно, было разработано до того, как поддержка функций-членов шаблона была широко распространена, поскольку в документации SGI STL есть различные примечания: "если ваша реализация не поддерживает членство шаблоны, то это невозможно". Для такого простого компонента, я думаю, было бы стимулом сделать что-то, что работает сегодня. Как только он существует, стандартизация может затем удалить его в пользу чего-то еще, но стоит ли нарушать существующий код? Если бы это была большая сделка, то либо вы, либо стандарт могли бы ввести функтор flexible_less, как вы описали.

Наконец, почему

template<class T>
bool operator()(T const& lhs, T const& rhs){
  return lhs < rhs;
}

а не

template<class T, class U>
bool operator()(T const& lhs, U const& rhs){
  return lhs < rhs;
}

Для пользовательских типов два могут отличаться. Да, это несправедливый вопрос, так как я не знаю, почему нет версии с двумя шаблонами std::less; -)