Saya bertanya-tanya bagaimana cara memeriksa dengan benar apakah std::function
kosong. Pertimbangkan contoh ini:
class Test {
std::function<void(int a)> eventFunc;
void registerEvent(std::function<void(int a)> e) {
eventFunc = e;
}
void doSomething() {
...
eventFunc(42);
}
};
Kode ini dikompilasi dengan baik di MSVC tetapi jika saya memanggil doSomething()
tanpa menginisialisasi eventFunc
kode tersebut jelas macet. Itu diharapkan tapi saya bertanya-tanya apa nilai dari itu eventFunc
? Kata debugger 'empty'
. Jadi saya memperbaikinya menggunakan pernyataan if sederhana:
void doSomething() {
...
if (eventFunc) {
eventFunc(42);
}
}
Ini berfungsi tetapi saya masih bertanya-tanya apa nilai non-inisialisasi std::function
? Saya ingin menulis if (eventFunc != nullptr)
tetapi std::function
(jelas) bukan penunjuk.
Mengapa murni jika berhasil? Apa keajaiban di baliknya? Dan, apakah ini cara yang benar untuk memeriksanya?
c++
c++11
std-function
NightElfik
sumber
sumber
eventFunc
itu bukanlah lambda; itu astd::function
. Anda dapat menyimpan lambda dalamstd::function
s, tetapi keduanya tidak sama.Jawaban:
Anda tidak memeriksa lambda kosong, tetapi apakah
std::function
memiliki target yang dapat dipanggil yang disimpan di dalamnya. Pemeriksaan ini terdefinisi dengan baik dan berfungsi karenastd::function::operator bool
memungkinkan konversi implisit kebool
dalam konteks di mana nilai boolean diperlukan (seperti ekspresi bersyarat dalamif
pernyataan).Selain itu, gagasan tentang lambda kosong tidak masuk akal. Di balik layar, kompilator mengubah ekspresi lambda menjadi definisi
struct
(atauclass
), dengan variabel yang Anda tangkap disimpan sebagai anggota data inistruct
. Operator panggilan fungsi publik juga ditentukan, yang memungkinkan Anda memanggil lambda. Jadi, apa lambda kosong itu?Anda juga dapat menulis
if(eventFunc != nullptr)
jika Anda mau, ini setara dengan kode yang Anda miliki dalam pertanyaan.std::function
mendefinisikanoperator==
danoperator!=
kelebihan untuk membandingkan dengan anullptr_t
.sumber
== nullptr
melakukan hal yang sama? Sepertinya ada seharusnya menjadi kelebihan bagi==
operator yang menyebabkan "kosong"std::function
untuk membandingkantrue
terhadapnullptr
: cplusplus.com/reference/functional/function/operatorsnullptr
akan bekerja juga,if(eventFunc != nullptr)
sama denganif(eventFunc)
pertanyaan di atas.std::function::operator bool
tidak mengizinkan konversi implisit kebool
. Ini ditandaiexplicit
, tetapi standar membuat pengecualian untuk konstruksi bahasa tertentu yang mengharapkan ekspresi boolean, menyebutnya "secara kontekstual dikonversi ke bool." Anda dapat menemukan potongan yang relevan dari bahasa standar dan penjelasannya di sini: chris-sharpe.blogspot.com/2013/07/…explicit
, itulah mengapa saya berhati-hati untuk menyatakan mengizinkan konversi implisit kebool
dalam konteks di mana nilai boolean diperlukan . Persis seperti inilah yang terjadi pada kode yang dipermasalahkan.Periksa di sini http://www.cplusplus.com/reference/functional/function/operator_bool/
Contoh
// 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; }
Keluaran
sumber
swap()
. Saya berpikir hasilnya mundur sampai saya menyadarinya.(Izinkan saya memberikan jawaban yang jelas.)
Anda dapat memeriksa apakah a
std::function
kosong denganstd::function::operator bool
.Contoh
#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; }
Keluaran
sumber