Почему `std :: all_of` не использует` std :: invoke`? - PullRequest
3 голосов
/ 14 октября 2019

В аналогичных вопросах (например, здесь ) отмечалось, что вы не можете передавать указатели методов класса в качестве предикатов на std::all_of.

Однако с C ++ 17 мы имеемstd::invoke, что должно облегчить std::all_of и аналогичным функциям принятие указателей на функции-члены (и даже переменные-члены).

Точнее, в GCC 9.2 следующее не компилируется:

#include <algorithm>
#include <vector>

struct S {
    bool check() const { return true; }
};

int main() {
    std::vector<S> vs;
    std::all_of(vs.begin(), vs.end(), &S::check);
}

Эта ссылка Годболта содержит пример кода и игрушечную версию all_of с использованием invoke.

Почему это ограничение? Я что-то пропустил? Я представлял, что когда стандартизировали std::invoke, его также следует применять к соответствующим функциям STL.

Ответы [ 2 ]

5 голосов
/ 14 октября 2019

Причина 1: Никто никогда не предлагал это. P0312R1 предложил сделать функции указателя на элемент вызываемыми в языке, но был отклонен (нет единого мнения относительно внесения этого изменения).

Причина 2: С лямбдами (и std::bind до этого) мотивация очень мала. Если S является стандартным типом (например, vector), параметр член-указатель будет недопустимым по другим причинам.

std::all_of(vs.begin(), vs.end(), [](auto const& s) {return s.check();});
4 голосов
/ 15 октября 2019

Следующее поколение алгоритмов (в пространстве имен std::ranges) принимает предикаты, которые вызываются с std::invoke, в точности так, как вы предлагаете (https://godbolt.org/z/uaPoJf):

std::ranges::all_of(vs.begin(), vs.end(), &S::check);

или короче ()https://godbolt.org/z/_qiO8G):

std::ranges::all_of(vs, &S::check);

Кроме того, они принимают дополнительный аргумент, называемый «проекцией», который представляет собой унарную функцию преобразования, передаваемую алгоритму, который применяется к каждому элементу до того, как алгоритм воздействует на элемент. Например (https://godbolt.org/z/gWY-OR):

std::ranges::all_of(vs, std::logical_not(), &S::check);

Вы уже можете использовать все вышеперечисленное с Кейси Картером cmcstl2 или с Эриком Ниблером range-v3 .

...