C ++ 11'de std :: function boş olup olmadığı nasıl doğru bir şekilde kontrol edilir?


100

A'nın std::functionboş olup olmadığını nasıl doğru bir şekilde kontrol edeceğimi merak ediyordum . Şu örneği düşünün:

class Test {
    std::function<void(int a)> eventFunc;

    void registerEvent(std::function<void(int a)> e) {
        eventFunc = e;
    }

    void doSomething() {
        ...
        eventFunc(42);
    }
};

Bu kod MSVC'de gayet iyi derlenir, ancak kodu doSomething()başlatmadan ararsam eventFuncaçıkça çöker. Bu bekleniyordu ama merak ediyordum da değeri eventFuncnedir? Hata ayıklayıcı diyor 'empty'. Ben de bunu basit if ifadesini kullanarak düzelttim:

   void doSomething() {
        ...
        if (eventFunc) {
            eventFunc(42);
        }
   }

Bu eserler ancak hala sigara başlatıldı değeri nedir merak ediyorum std::function? Yazmak isterdim if (eventFunc != nullptr)ama std::function(belli ki) bir işaretçi değil.

Neden işe yarıyorsa saf? Arkasındaki sihir nedir? Ve bunu kontrol etmenin doğru yolu bu mu?


8
Bunun eventFuncbir lambda olmadığını unutmayın ; bu bir std::function. Lambdaları std::functions olarak saklayabilirsiniz , ancak aynı şey değildirler.
templatetypedef

3
Haklısın, karışıklığı önlemek için başlığı değiştirdim. Teşekkürler.
NightElfik

Yanıtlar:


108

Boş bir lambda olup olmadığını kontrol etmiyorsunuz, ancak std::functioniçinde saklanan çağrılabilir bir hedef olup olmadığını kontrol ediyorsunuz . Kontrol iyi tanımlanmıştır ve std::function::operator boolbu nedenle, boolboole değerlerinin gerekli olduğu bağlamlarda (bir ifadedeki koşullu ifade gibi) örtük dönüşüme izin verdiği için çalışır if.

Ayrıca, boş bir lambda fikri pek mantıklı değil. Sahne arkasında, derleyici bir lambda ifadesini bir struct(veya class) tanımına dönüştürür, yakaladığınız değişkenler bunun veri üyeleri olarak depolanır struct. Lambda'yı çağırmanıza izin veren bir genel işlev çağrısı operatörü de tanımlanmıştır. Peki boş bir lambda ne olur?


İsterseniz yazabilirsiniz if(eventFunc != nullptr), sorudaki koda eşdeğerdir. a ile karşılaştırmak için std::function tanımlar operator== ve operator!=aşırı yüklemeler nullptr_t.


1
== nullptrYine de aynı şeyi yapmıyor mu ? İçin bir aşırı yük olacaksa gerekiyordu gibi görünüyor =="boş" bir neden operatörü std::functionkarşılaştırma truekarşı nullptr: cplusplus.com/reference/functional/function/operators
Kyle Strand

3
@KyleStrand Evet, nullptrçalışacak ile kıyaslandığında da yukarıdaki soruya if(eventFunc != nullptr)eşdeğerdir if(eventFunc).
Praetorian

3
Teknik olarak, 'a std::function::operator boolörtük dönüşüme izin vermez bool. Sonuçta işaretlenmiştir explicit, ancak standart, boole ifadeleri bekleyen belirli dil yapıları için bir istisna yapar ve bunu "bağlamsal olarak bool'a dönüştürülür" olarak adlandırır. İlgili standart kod
bcrist

@bcrist Evet, boole dönüşüm operatörünün olduğunu explicitbiliyorum, bu yüzden boole değerlerinin gerekli olduğu bağlamlarda örtük dönüşüme izinbool verdiğini belirtmeye dikkat ettim . Söz konusu kodda olan tam olarak budur.
Praetorian

5
@Praetorian Belirtmeye çalıştığım nokta, standardın "örtük dönüştürme" ifadesine çok özel bir anlam ataması ve aynı zamanda çok özel bir anlamı olan "bağlamsal dönüşümden bool'a" belirgin bir şekilde farklı olmasıdır. Burada "bir" ilişkisi yok. Yeni başlayanların muhtemelen örtük / açık / bağlamsal dönüşüm arasındaki farkı hemen bilmelerine gerek olmadığını anlıyorum, ancak doğru kelimeleri bilinçaltında öğrenmek, daha sonra eski alışkanlıklarını kırmak zorunda kalmaktan daha iyidir.
bcrist

23

Burayı kontrol edin http://www.cplusplus.com/reference/functional/function/operator_bool/

Misal

// function::operator bool example
#include <iostream>     // std::cout
#include <functional>   // std::function, std::plus

int main () {
  std::function<int(int,int)> foo,bar;
  foo = std::plus<int>();

  foo.swap(bar);

  std::cout << "foo is " << (foo ? "callable" : "not callable") << ".\n";
  std::cout << "bar is " << (bar ? "callable" : "not callable") << ".\n";

  return 0;
}

Çıktı

foo çağrılamaz.

bar çağrılabilir.


31
Bence bu cevap swap(). Ben anlayana kadar çıktının geriye doğru olduğunu düşünüyordum.
cp.engr

1

(Net bir cevap vereyim.)

A std::functionile boş olup olmadığını kontrol edebilirsiniz std::function::operator bool.

true: eğer nesne çağrılabilirse.
false: aksi takdirde (nesne boş bir işlevdir)

Misal

#include <iostream>
#include <functional>

int main ()
{
    std::function<int(int,int)> foo = std::plus<int>();//assigned: not empty
    std::function<int(int,int)> bar;//not assigned: empty

    std::cout << "foo is " << (foo ? "not empty" : "empty") << ".\n";
    std::cout << "bar is " << (bar ? "not empty" : "empty") << ".\n";

    return 0;
}

Çıktı

foo boş değil.
bar boş.


2
Sonuç dizeleriniz değiştirilir.
Sophit

@Sophit Emin misiniz? ;)
zwcloud

1
Yorumunuz foo'nun boş olmadığını ve çıktının aynı fikirde olmadığını söylüyor. Yorumunuza katılıyorum.
Sophit
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.