使用模板 lambda C++20 连接函数调用

Concatenate function calls with a template lambda C++20

我有一个连接函数调用的模板函数:

template<typename Callable, typename... Callables>
decltype(auto) concat_callable(Callable callable, Callables... callables)
{
    if constexpr (sizeof...(callables) > 0) {
        return [=]
        <typename... Args>
        (Args&&... args) {
            return callable(concat_callable(callables...)(std::forward<Args>(args)...));
        };
    }
    else {
        return callable;
    }
}

我想调用以下函数:

std::string& f_1(std::string& str)
{
    return str;
}

std::string& f_2(std::string& str)
{
    return str;
}

std::string& f_3(std::string& str)
{
    return str;
}

我想这样称呼它:

std::string str{ "sample text" };
concat_callable(f_1, f_2, f_3)(str);

相当于:

f_1(f_2(f_3(str)));

但目前我遇到错误 'std::string &(std::string &)': cannot convert argument 1 from 'std::string' to 'std::string &'

出于某种原因,当我只使用两个函数时它编译得很好,例如:

concat_callable(f_1, f_2)(str);

请问有什么解决办法吗?

-> decltype(auto) 作为尾随 return 类型添加到 lambda。如果没有这个,来自 return 类型的引用将被丢弃。

    return [=]
    <typename... Args>
    (Args&&... args) -> decltype(auto) {
        return callable(concat_callable(callables...)(std::forward<Args>(args)...));
    };

Invocation concat_callable with f1,f2 可以翻译为:

conact_callable(f1,f2)
    return f1(f2) 

这很好用,f1 需要 string&f2 return 参考。

但是有三个或更多可调用对象:

concact_callable(f1,f2,f3)
    return f1( concat_callable(f2,f3) )

    /*
    here is a problem because concat_callable discards reference
    from return type and temporary string cannot be bound to
    Lvalue reference.
    */

Demo