Reference: here.
The return of overloaded operator should be a reference, otherwise return-by-code will create a (temporary) rvalue that cannot be passed to the next operation f2 by non-const reference. i.e., rvalue cannot be non-const referenced.
#include <vector>
#include <iostream>
#include <functional>
template<typename T, typename FN>
requires std::invocable<FN, T&> // diff std::invocable?
std::vector<T>& operator| (std::vector<T>& vec, FN fn) noexcept {
for(auto& e: vec) {
fn(e);
}
return vec;
}
int main(){
std::vector v{1, 2, 3};
auto f1 = [](int& i) {i *= i; };
std::function f2 {[](const int& i) {std::cout << i << ' '; } };
v | f1 | f2;
}```