2015-11-15 46 views
7

Std :: yer tutucularını kullanarak işlevin aritliğini açıkça bilmem/belirtmek zorunda kalmadan bir fonksiyonun ilk argümanını bağlayan bir fonksiyona sahip olmak istiyorum BindFirst. Müşteri kodunun böyle bir şey görmesini isterim.işlevinin ilk argümanını, onun nesnesini bilmeden bağla

#include <functional> 
#include <iostream> 

void print2(int a, int b) 
{ 
    std::cout << a << std::endl; 
    std::cout << b << std::endl; 
} 

void print3(int a, int b, int c) 
{ 
    std::cout << a << std::endl; 
    std::cout << b << std::endl; 
    std::cout << c << std::endl; 
} 

int main() 
{ 
    auto f = BindFirst(print2, 1); // std::bind(print2, 1, std::placeholders::_1); 
    auto g = BindFirst(print3, 1); // std::bind(print3, 1, std::placeholders::_1, std::placeholders::_2); 
    f(2); 
    g(2,3); 
} 

BindFirst nasıl uygulanabilir? C++ 11'inde

cevap

8

:

#include <type_traits> 
#include <utility> 

template <typename F, typename T> 
struct binder 
{ 
    F f; T t; 
    template <typename... Args> 
    auto operator()(Args&&... args) const 
     -> decltype(f(t, std::forward<Args>(args)...)) 
    { 
     return f(t, std::forward<Args>(args)...); 
    } 
}; 

template <typename F, typename T> 
binder<typename std::decay<F>::type 
    , typename std::decay<T>::type> BindFirst(F&& f, T&& t) 
{ 
    return { std::forward<F>(f), std::forward<T>(t) }; 
} 

DEMO 1

C++ 14'ünde:

#include <utility> 

template <typename F, typename T> 
auto BindFirst(F&& f, T&& t) 
{ 
    return [f = std::forward<F>(f), t = std::forward<T>(t)] 
      (auto&&... args) 
      { return f(t, std::forward<decltype(args)>(args)...); }; 
} 

DEMO 2

+0

Ben std :: decay' neden 'bilebilir Kullanılmış? – billz

+0

@billz Burada, BindFirst'e iletilen argümanların kopyalarını (muhtemelen hareket ettirilmiş) saklamak istiyoruz. Kesinlikle referansları saklamak istemiyorsunuz, onların nezaketleri/uçuculuğu ilginizi çekmiyor. 'T' için 'T && = int && 'saklamak istediğinizi söyleyin –