是否可以使用默认的泛型参数在C++中定义lambda?

Pao*_*tto 11 c++ lambda auto c++11 c++14

是否可以使用默认的泛型参数在C++中定义lambda?

int main(){
    auto lambda = [](auto i = 0){return i;};
    std::cout<<lambda()<<"\n"; // this does not compile
    std::cout<<lambda(4)<<"\n"; // this does compile
    auto lambda2 = [](int i = 0){return i;};
    std::cout<<lambda2()<<"\n"; // this is also OK
}
Run Code Online (Sandbox Code Playgroud)

我想知道是否有可能重现类似这个仿函数的东西,为什么不呢

struct Lambda{
    template<typename T=int>
    auto operator()(T i=1){ return i;}
};
Run Code Online (Sandbox Code Playgroud)

Max*_*kin 2

您可以使用包装器来做到这一点:

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";
}
Run Code Online (Sandbox Code Playgroud)

另一种 C++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';
}
Run Code Online (Sandbox Code Playgroud)

但有点次优,因为涉及 的两个副本lambda:一个副本位于 中,另一个是堆栈上的ComposeF原始副本。lambda如果lambda是可变的那将是一个问题。

  • …需要注意的是,与“true”默认参数不同,初始化“arg”的表达式仅在创建函子时计算一次。这也可能会产生一些意外的生命周期交互,例如,当 `DefaultArg` 是 `std::initializer_list` 的实例时,如 `bool my_is_sorted(const std::vector&lt;int&gt; &amp;v);` ... `with_default_arg(my_is_sorted, {1,2,3}) // UB 待命`。 (2认同)