Я выясняю способ программирования своего рода FunctionalInterface - подобных Java - на С++ (хотя он уже предоставляет эти функции).
Я практикуюсь с Predicate на данный момент. Собственно я это уже сделал:
namespace _utils{
namespace _functional{
template <typename T>
class Predicate: public FunctionalI{
protected:
std::function<bool(T)> predicate;
public:
Predicate(std::function<bool(T)> predicate){
this->predicate = predicate;
}
inline bool test(T t){
return this->predicate(t);
}
};
}
}
А это main.cpp:
bool foo(_functional::Predicate<int> predicate){
return predicate.test(2);
}
int main(){
_functional::Predicate<int> tmp = _functional::Predicate<int>([] (int x) -> bool{ return x == 2; });
std::cout << foo(tmp);
return 0;
}
Теперь, конечно, это работает!
Мой вопрос о том, как я могу сделать краткое изложение этого лямбда-выражения? Я имею в виду, есть ли способ передать «напрямую» лямбда-выражение (без передачи его конструктору Predicate), а затем позволить ему создать объект Predicate с правильным лямбда-выражением.
Я посмотрел на использование алиасинга и даже на функтор с operator(), но они мне не помогли (может быть, я не смог это сделать)
Пример main.cpp, которого я хочу достичь:
bool foo(_functional::Predicate<int> predicate){
return predicate.test(2);
}
int main(){
// To much stuff to write
//std::cout<<foo(_functional::Predicate<int>( [] (int x) -> bool{ return x == 2; } ));
//What I whish to reach
foo([] (int x) -> bool{return x == 2;} );
return 0;
}
Еще один вопрос для краткого изложения лямбда-выражения: есть ли способ сделать неявным возвращаемый тип лямбда и даже ключевое слово return?
CTAD может помочь.
@ Jarod42 Только если вы настаиваете на воспроизведении API, который использует Java, потому что он не может перегружать операторы. Весь класс Predicate не имеет смысла в C++.
Не имеет отношения к вопросу: все идентификаторы, начинающиеся с подчеркивания, зарезервированы в области глобального пространства имен.
-> bool не нужен, выводится из return x == 2;. возврат не может быть опущен.
Даже если вы не хотите использовать рекомендуемый способ передачи лямбды с помощью параметра шаблона, в чем смысл Predicate? Разве это не просто ограниченное std::function? Разве псевдонима template<typename T> using Predicate = std::function<bool(T)>; не будет достаточно?
@PasserBy О, спасибо! Это работает. Теперь я собираюсь изучить ссылку на rvalue, как вы предложили.
@user17732522 user17732522 Я просто тренируюсь с ним. Да, я действительно больше узнал об алиасинге. О подчеркивании и пространстве имен я только что прочитал об этом; Спасибо за это
@DynoZ, если вы хотите ограничить тип, правильным способом, вероятно, будет концепция и ограничение (с общим вызываемым) в С++ 20 или обычные sfinae раньше. Хотя tbf std::function, вероятно, легче выучить, и у него тоже есть свое применение (стирание шрифта).





Проблема с foo( [] (int x) -> bool{return x == 2;} ); заключается в том, что он пытается выполнить два неявных преобразования (лямбда в std::function и std::function в Predicate). С++ не позволяет вам это сделать. Вместо этого вы можете явно указать, что вы инициализируете Predicate, добавив фигурные скобки:
foo( { [] (int x) -> bool{return x == 2;} } );
// ^ initialise Predicate object ^
Или создайте конструктор шаблонов, как предложено в комментариях:
class Predicate : public FunctionalI {
protected:
std::function<bool(T)> predicate;
public:
template <typename PredType>
Predicate(PredType predicate) : predicate{ std::move(predicate) }
{
// use member init list instead of reassigning object in constructor
}
// ...
};
std::function не может быть объявлен, если не было предоставлено предыдущее объявление шаблона? По крайней мере, ожидается "авто"
Ой, извини. Я только что понял свою ошибку в неправильном понимании вашего ответа. Во всяком случае, мне тоже помогло. Собственно, это как раз то, что я искал. Спасибо!
template<typename T> bool foo(T&& t) { return t(2); }