Почему std :: forward_list :: remove и std :: erase есть разные типы для значения? - PullRequest
1 голос
/ 11 апреля 2020

std::forward_list имеет функцию-член :

size_type remove(const T& value);

и функцию, не являющуюся членом std::erase, объявленную следующим образом:

template<class T, class Alloc, class U>
typename forward_list<T, Alloc>::size_type
    erase(forward_list<T, Alloc>& c, const U& value);

Обратите внимание, что функция, не являющаяся членом std::erase, имеет другой тип U для value; в то время как функция-член remove просто использует тип T для value.

Почему std::erase просто не использует тип T для value?

Есть ли какое-либо логическое обоснование несоответствия?

Ответы [ 2 ]

2 голосов
/ 11 апреля 2020

Я вижу практическую причину. И это связано с трудностями, вызванными выводом аргументов шаблона. Представьте себе эту гипотетическую функцию:

template<typename T>
void foo(std::forward_list<T> const&, T const&) {}

Что вы получаете за этот вызов?

std::forward_list<double> l;
foo(l, 1);

Ответ заключается в том, что вы получаете ошибку при выводе аргумента шаблона. Согласно одному аргументу T является двойным, но согласно другому это int. Если бы я написал erase, я бы также использовал два разных аргумента шаблона, хотя бы для того, чтобы избежать подобных проблем в невинном коде.

Теперь remove не является шаблоном-членом, это обычный функция-член любой специализации. Таким образом, вы можете написать без проблем:

std::forward_list<double> l;
// later
l.remove(1);

1 является целым числом, оно не соответствует double, ожидаемому remove. Однако это не проблема. Потому что remove является регулярной функцией-членом конкретной специализации, и неявное преобразование возможно.

2 голосов
/ 11 апреля 2020

Как указано на cppreference.com :

В отличие от std :: forward_list :: remove, стирание принимает гетерогенные типы, а не вызывает преобразование к типу значения контейнера перед вызовом оператора == .

Итак, для std::erase() достаточно указать operator== для T и U без наложения ограничение на U конвертируемость в T, что дает больше свободы по сравнению с remove() функцией-членом.

...