2016-01-26 102 views
7

我想創建拉姆達將接受任何數量的參數一樣:這裏將所有參數拉姆達

template <typename... Args> 
void f(Args... args) { 
    auto l = [args...]() { 
     g(args...); 
    } 
    // use l 
} 

問題是,它不動,只工種。如果它只有1個精算,我會做不像

void f(Arg arg) { 
    auto l = [arg = std::move(arg)]() { 
     g(move(arg)); 
    } 
} 

如何將所有參數移動到lambda?

回答

8
template <class... Args> 
void f(Args... args) { 
    auto l = [tup=std::make_tuple(std::move(args)...)] { 
    std::apply([](auto&&...args){ 
     g(decltype(args)(args)...); 
    }, tup); 
    }; 
} 

有點噁心。

將它們打包成一個元組,然後用std::apply解開元組。如果您缺少std::apply請自己寫一個等值的。

如果您想用rvalues調用g,請將外部lambda設置爲mutable,並將move元組設置爲內部lambda。

如果您想要訪問外部或類似的參數,內部lambda可以默認捕獲&

我們甚至可以抽象這種模式有點:

template<class F, class...Args> 
auto forward_capture(F&& f, Args&&...args) { 
    return [ 
    f=std::forward<F>(f), 
    tup=std::make_tuple(std::forward<Args>(args)...) 
    ]{ 
    return std::apply(f, tup); 
    }; 
} 

使用:

template <typename... Args> 
void f(Args... args) { 
    auto l = forward_capture(
    [](auto&&...args) { 
     g(args...); 
    }, 
    std::move(args)... 
); 
    // use l 
} 

如果你想捕捉榜第一,我們可以做到這一點:

template<class...Args> 
auto forward_capture(Args&&...args) { 
    return [ 
    tup=std::make_tuple(std::forward<Args>(args)...) 
    ](auto&& f)mutable{ 
    return [ 
     f=decltype(f)(f), 
     tup=std::move(tup) 
    ]{ 
     return std::apply(f, tup); 
    }; 
    }; 
} 

使用:

template <typename... Args> 
void f(Args... args) { 
    auto l = forward_capture(std::move(args)...)(
    [](auto&&...args) { 
     g(args...); 
    } 
); 
    // use l 
} 

它具有我們有3個嵌套lambda的「優勢」。

更加有趣:

template<class...Args> 
struct arrow_star { 
    std::tuple<Args...> args; 
    template<class F> 
    auto operator->*(F&& f)&& { 
     return [f=std::forward<F>(f),args=std::move(args)]()mutable{ 
     return std::experimental::apply(std::move(f), std::move(args)); 
     }; 
    } 
}; 
template<class...Args> 
arrow_star<std::decay_t<Args>...> forward_capture(Args&&...args) { 
    return {std::make_tuple(std::forward<Args>(args)...)}; 
} 
template<class...Args> 
auto f(Args... args) 
{ 
    return 
    forward_capture(std::move(args)...) 
    ->* 
    [](auto&&...args){ 
     g(decltype(args)(args)...); 
    }; 
} 

live example

+0

不是很漂亮,但作品:) – RiaD

+0

@RiaD而我在這裏,這裏有2個變種。 ;) – Yakk

+0

我有一個關於捕獲與初始值設定項的問題。我讀過它們主要是用於移動類型的,但是不能做'[x = std :: move(x)]'作爲引用然後移動 - >'[&] {std: :移動(X); }'?將其移入捕獲列表似乎對我未經訓練的眼睛來說是多餘的。 – 0x499602D2