Ответ 1
Вы можете сделать это с помощью обертки:
template<class F, class DefaultArg>
struct DefaultArgWrapper
{
F f;
DefaultArg default_arg;
template<class... Args>
decltype(auto) operator()(Args&&... args) {
return f(std::forward<Args>(args)...);
}
decltype(auto) operator()() {
return f(default_arg);
}
};
template<class F, class DefaultArg>
DefaultArgWrapper<F, DefaultArg> with_default_arg(F&& f, DefaultArg arg) {
return {std::move(f), std::move(arg)};
}
int main(){
auto lambda = with_default_arg([](auto i){return i;}, 0);
std::cout<<lambda()<<"\n";
std::cout<<lambda(4)<<"\n";
}
Альтернативное решение С++ 17:
template<class... F>
struct ComposeF : F... {
template<class... F2>
ComposeF(F2&&... fs)
: F(std::forward<F2>(fs))...
{}
using F::operator()...;
};
template<class... F>
ComposeF<std::decay_t<F>...> composef(F&&... fs) {
return {std::forward<F>(fs)...};
}
int main() {
auto lambda = [](auto i) { return i; };
auto f = composef(lambda, [&lambda](int i = 0) { return lambda(i); });
std::cout << f() << '\n';
std::cout << f(1) << '\n';
}
Немного ComposeF
, хотя есть две копии lambda
: одна копия в ComposeF
, другая - оригинальная lambda
в стеке. Если lambda
изменчива, это будет проблемой.