2014-04-07 20 views
5

ben gibi auto kullanabilirsiniz varsayılan argümanı ile lambda işleve bir std :: işlev değişkeni ayarlamak için yapı. Bir yapıda auto kullanamıyorum.Bir std :: function değişkenini varsayılan argümanlarla nasıl tanımlamalıyım? Bu 10.</p> <p>yazdırır</p> <pre><code>auto foo = [](int x = 10){cout << x << endl;}; foo(); </code></pre> <p>Ama foo değişkeni bir ikamet istiyorum:

std::function<void(int x)> foo = [](int x = 10){cout << x << endl;}; 
foo(); //error: no match for call to ‘(std::function<void(int)>)()’ 

: std :: fonksiyonlu auto değiştirilmesi

struct Bar 
{ 
    std::function<void(int x = 10) foo = [](int x = 10}(cout << x << endl}; //error: default arguments are only permitted for function parameters 
}; 
Bar bar; 
bar.foo(); 

veya yapı olmadan

struct Bar 
{ 
    std::function<void(int) foo = [](int x = 10}(cout << x << endl}; 
}; 
Bar bar; 
bar.foo(); //error: no match for call to ‘(std::function<void(int)>)()’ 

ve std :: fonksiyonu için auto değiştirilmesi

struct Bar 
{ 
    auto foo = [](int x = 10}(cout << x << endl}; //error: non-static data member declared ‘auto’ 
}; 
Bar bar; 
bar.foo(); 

Peki nasıl foo ilan etmeliyim?

+0

Varsayılan argümanlarla 'std :: function' yapmanın bir yolu yoktur. –

cevap

4

std::function imza sen ve sen değil atamak/inşa nasıl adlandırmak nasıl plan dayanmaktadır. Eğer iki farklı yolu onu aramak istediğiniz beri, olduğu gibi farklı std::function nesnelere saklamak gerekir: Alternatif

struct Call 
{ 
    template<typename F> 
    explicit Call(F f) : zero_(f), one_(std::move(f)) {} 

    void operator()() { zero_(); } 
    void operator()(int i) { one_(i); } 

    std::function<void()> zero_; 
    std::function<void(int)> one_; 
}; 

, sadece tip silinti kendiniz (perde arkasında ne std::function) yapabilirsiniz lambda'yı aşağıdaki gibi bir kez saklayın:

class TECall 
{ 
    struct Concept 
    { 
     Concept() = default; 
     Concept(Concept const&) = default; 
     virtual ~Concept() = default; 

     virtual Concept* clone() const = 0; 

     virtual void operator()() = 0; 
     virtual void operator()(int) = 0; 
    }; 

    template<typename T> 
    struct Model final : Concept 
    { 
     explicit Model(T t) : data(std::move(t)) {} 
     Model* clone() const override { return new Model(*this); } 

     void operator()() override { data(); } 
     void operator()(int i) override { data(i); } 

     T data; 
    }; 

    std::unique_ptr<Concept> object; 

public: 
    template<typename F> 
    TECall(F f) : object(new Model<F>(std::move(f))) {} 

    TECall(TECall const& that) : object(that.object ? that.object->clone() : nullptr) {} 
    TECall(TECall&& that) = default; 
    TECall& operator=(TECall that) { object = std::move(that.object); return *this; } 

    void operator()() { (*object)(); } 
    void operator()(int i) { (*object)(i); } 
}; 
1

Bu size yardımcı olup olmayacağını bilmez, ancak bir lambda'yı şablonlu bir yapıya kaydedebilirsiniz.

template <typename F> 
struct Bar { 
    F foo; 
    Bar (F fun): foo (std::move (fun)) {} 
}; 

auto f = [](int x = 10) {cout << x << endl;}; 
Bar<decltype (f)> bar (f); 
bar.foo(); 

auto makeFun = [](){return [](int x = 10) {cout << x << endl;};}; 

Bar<decltype (makeFun())> bar2 (makeFun()); 
bar2.foo(); 
İlgili konular