2012-07-13 22 views
10

Ben bir ana işlevi vardır bu programı, hangi iç, böyle iki soket oluşturma yazdım:Sinyal işlemek için Auto ve Lambda kullanma?

Şimdi
int sockfd1 = socket(AF_INET, SOCK_STREAM, 0); 
int sockfd2 = socket(AF_INET, SOCK_STREAM, 0); 

onlarla bir şeyler yapmak ve kullanıcı bastığında Ctrl + C sonlandırmak için süreç, ben prizler düzgün kapatmak emin olmak istiyorum, bu yüzden bunu:

auto sigTermHandler = [&] (int param) { close(sockfd1); close(sockfd2); }; 
signal(SIGTERM, sigTermHandler); 

Ama bu g++ -std=gnu++0x <filename>.cpp olarak derlenmiş aşağıdaki derleme hatası atar:

error: cannot convert ‘main(int, char**)::<lambda(int)>’ to ‘__sighandler_t {aka void (*)(int)}’ for argument ‘2’ to ‘void (* signal(int, __sighandler_t))(int)’ 

Sinyal işlemek için lambda bu şekilde kullanmak mümkün değil mi? Tavsiye lütfen.

P.S. Bunu bir yıkıcıya koyabileceğimi biliyorum, eğer uygun bir OOP yaptıysam, ama bunun işe yarayıp yaramadığını merak ediyorum.

cevap

15

Basit bir işlev işaretçisi çağırırken yakalama özelliğini lambda'dan kullanamazsınız. Bir yakalama olmayan bir lambda fonksiyonu da, bir işlev işaretçisi dönüştürülebilen standart durumları:

5.1.2 (6) herhangi bir lambda yakalama ile bir lambda-ifadesi için kapalı tip bir halka sanal olmayan var açık olmayan const işaretleme işlevini, aynı parametre ve işlev türlerine sahip olarak işlev göstermesi için kapatma türünün işlev çağrısı işleci. Bu dönüşüm işlevi tarafından döndürülen değer, çağrıldığında, kapatma türünün işlev çağrısı işlecini çağırmakla aynı etkiye sahip olan bir işlevinin adresi olacaktır. Eğer lambda bunları kullanabiliriz, ardından

signal(SIGTERM, [foo](int signum) { /* use foo here */ }); 

Aslında sockfd1 ve global değişkenler olarak sockfd2 tutabilir ve:

signal(SIGTERM, [](int signum) { /* ... */ }); 

Ama bu:

Örneğin, bu işleri işlevi. Ama bu açıkça iyi bir tasarım değil. Yani RAII tasarımını kullanmak daha iyidir. Program sonlandırılırsa, soketler yine de kapanacaktır (@Dani işaret ediyor).

0

Bir program kapatıldığında soketler her zaman kapalı olacaktır, bunun için endişelenmenize gerek yoktur. kullanıcı CTRL-C bastığı zaman mantıksal kaynak kullanım dert varsa
, yıkıcılar koymak, ancak bu denilen olmayacak

1

geç ama birisi böyle bir çözüm ihtiyacı varsa birisi bir sarmalayıcı std::function kullanabilirsiniz Biraz değişkenleri yakalayabilen bir lambda tutmak için:

#include <functional> 
#include <iostream> 

namespace { 
std::function<void(int)> shutdown_handler; 
void signal_handler(int signal) { shutdown_handler(signal); } 
} // namespace 

int main(int argc, char *argv[]) { 
    std::signal(SIGINT, signal_handler); 
    MyTCPServer server; 
    shutdown_handler = [&](int signal) { 
    std::cout << "Server shutdown...\n"; 
    server.shutdown(); 
    }; 
    server.do_work_for_ever(); 
} 
İlgili konular