2016-03-31 43 views
2

Bazı lambda işlevleri için benzersiz olacak ve lambda'nın lansmanları arasında sürecek bir değişken oluşturmanın bir yolu var mı?
Daha dikkatli açıklaması: Bazı değerine başlatılan değişkenle lambda istiyoruz ve bunun değişken başlatması arasında sürmelidir:Lambdaya özgü değişken

std::function<void(void)> a=[]() 
{ 
    /*here we declare variable X and initialize it to 0*/; 
    std::cout<<X++; 
}; 
a();a(); 

Yani bu 01

yazdırmalısınız Ama aynı zamanda ben "emin olmak gerekir önceki bölümde sonra bu

std::function<void(void)> b=a; 
b();b(); 

denedim 01.

çıktısını bu yüzden X 'a" için benzersizdir' Statik değişkenler kullanarak, ancak kopyalar arasında paylaşılırlar (böylece bu iki parça 0123'ü yazdırır).

Peki, bunu yapmanın bir yolu var mı?

+1

Neden karmaşık? Bir sınıf yazamaz mısın? – jrok

+0

Biraz karmaşık bir sınıf sistemim var, bunlardan biri kullanıcı tarafından tanımlanan özel işlevler olarak lamda kullanıyor. Ve bu işlevler için veri depolama amacıyla soyut sınıfları kullanmaktan kaçınmak istiyorum. Ayrıca bu sınıfın nesneleri kopyalanabilir, statik değişkenler gibi basit çözümler işe yaramıyor. – jammer312

+0

Bu tür "kopyalama" ne demektir. – Barry

cevap

2

Kopyaları sıfırlamak istediğinizde. bunu yapar verileri yapın:

template<class T> 
struct no_copy { 
    T init; 
    T current; 
    operator T&(){ return current; } 
    operator T const&()const{ return current; } 
    no_copy(T&& i):init(i), current(init) {} 
    no_copy(no_copy const&o):init(o.init), current(init) {} 
    no_copy(no_copy &&o):init(std::move(o.init)), current(init) {} 
}; 
template<class T> 
no_copy<std::decay_t<T>> make_no_copy(T&& t){ 
    return {std::forward<T>(t)}; 
} 

Sonra C++ 14'te, kolay: dışarı 01

std::function<void(void)> a=[X=make_no_copy(0)]()mutable 
{ 
    std::cout<<X++; 
}; 
a();a(); 

baskılar. C++ 11 yılında

:

auto X=make_no_copy(0); 
std::function<void(void)> a=[X]()mutable 
{ 
    std::cout<<X++; 
}; 
a();a(); 

o da çalışır, ancak biraz daha çirkin.

Lambda'nın dışında bulunan 'un bir kopyası dışında, C++ 11 sürümü davranıştaki C++ 14 sürümüyle aynıdır.

live example

+1

OP'nin tam olarak istediği şey bu değil. Şimdi, bu parçayı bir(); bir(); "otomatik b = a; b(); b()". OP, soruyu okuduğuma dayanarak b'nin sayaç sıfırlamasını ister. –

+0

OP, işlev nesnesi kopyalandığında üyenin sıfırlanmasını ister. – jrok

+0

@sam ah, bu tuhaflığı kaçırdı. Bunu yapmak için tür eklendi. – Yakk

3

Ben değişken lambda'lar yeterli olduğunu sanmıyorum. Fonksiyon göstergesini kopyaladığınızda, aynı zamanda sayacı kopyalayarak, değiştirilebilir yakalama da kopyalanacaktır. Soruyu okuduğumda, lambda'nın her kopyasının ilk değiştirilebilen yakalama ile başlaması gerekir.

Bir kopya kurucu ile özel bir sınıf yakalamanız gerekir, bunu yapmak için:

#include <functional> 
#include <iostream> 

class my_class { 

public: 
    int n=0; 

    my_class() 
    { 
    } 

    my_class(const my_class &b) 
    { 
    } 
}; 

int main() 
{ 

    std::function<void(void)> a= 
     [my_class_instance=my_class()]() 
     mutable 
     { 
      std::cout << my_class_instance.n++; 
     }; 
    a(); 
    a(); 

    auto b=a; 

    b(); 
    b(); 

} 

bundan sonucudur:

bir yardımcı sınıf olmadan
0101 

, eşdeğer kod kullanarak sadece değişken lambda'lar sorununun


Benim okuma üretecek olan eski b olduğunu Davranış istenir.

+0

Sınıf üyesi mutable olarak bildirilmişse, lambda'nın kendisinin de değişmez yakalamalar kullanmasına bile gerek yoktur. Bunu doğrulamak için çok tembel, ama bana da doğru geliyor ... –

0

Tek seçeneği "sıfırlamak" için kopya yapıcısını kullanıyor musunuz? Aynı başlangıç ​​ortamından taze lambdas yayan bir fabrika işlevi yazmanız gerekmiyor mu?

Bir kopyanın bir semantik kötüye kullanımı kötüye kullanılmasından sonra A öğelerinden farklı olduğunu ummak.

auto make_counter() -> std::function<int()> { 
    return [x=0]() mutable { return x++; }; 
} 

auto a = make_counter(); 
std::cout << a() << " " << a() << "\n"; 

auto b = make_counter(); 
std::cout << b() << " " << b() << "\n"; 
+0

Soru, lambda'nın başka bir örneğini oluşturmak yerine, silinen 'std :: function' silindiğinde, sayacın otomatik olarak sıfırlanmasını gerektirir. . "Semantiğin kötüye kullanımı" olup olmama ya da olmama meselesinin biraz dışındadır. Belki de, belki de değil, tartışacak başka biri için. Ancak, bu, ilginç bir teknik soru, kendi esasına göre geçerli. –

+0

@SamVarshavchik "Soru açıkça gerektirir" - Biliyorum. OP intihar etmek için nasıl bir tavsiye istediyse, bu tavsiyeyi verir misiniz? Yoksa ona yapmamasını mı tercih edersin? Tüm engellemek istediğim, bir XY probleminin Y'sine cevap vermek. –

+0

Teknik bir soruyu intiharla karşılaştırmak biraz gergin. –

İlgili konular