2014-09-04 33 views
6

variadic argümanlarla bir fonksiyon kaydetmek için kullanılabilir Mevcut sistem durumuna bağlı olarak farklı işlevleri çeşitli geri çağrılara bağlayarak; iyi çalışıyor. örneğin,std Can :: fonksiyonunu ben geri arama fonksiyonları bir demet içeren başvurumun etrafında geçmesi bir yapıya sahip

std::function<int (const char * format, ...)> printToStdOut; 

Bu değil çalışır: Şimdi yapmak istiyorum ne

benzer printf'e bağımsız değişken sayıları içeren imzalarla ekstra geri aramaları bir çift eklemektir. C++ sözdizimi bu alanı üzerinden

error C2027: use of undefined type 'std::_Get_function_impl<_Fty>' 

Hala yolumu hissediyorum ve çok Buradan devam etmelidir konusunda herhangi bir tavsiye takdir ediyorum: Visual C++, ben bildiren bir hata iletisi alabilirsiniz. Sistem durumuna göre

myCallbackTable.printToStdOut("I've just eaten %d bananas\r\n", nBananas); 

... ve çıkış bir dosyaya veya bir GUI penceresine, bir konsola yönlendirilmiş olması: My durduğu hedef çizgisinde bir çağrı yapmak mümkün olduğu .

+0

o, bir [ 'std :: ostream' kullanmalıdır size ilgilenen sadece çıkış ise ] (http://www.cplusplus.com/reference/ostream/ostream/ostream/) bunun yerine. – nwp

+0

'std :: function' yalnızca' R (ArgTypes ...) 'formundaki işlev türleri için tanımlanmıştır, burada' ArgTypes ...'bir tür parametre paketinin (yani, (muhtemelen boş) bir liste listesi) bir paket genişlemesidir. Yani, C stili değişken bir fonksiyona izin verilmez. –

+0

AFAIK, değişken işlevler için std :: function işlevinin hiçbir özelleşmesi, burada [https://www.daniweb.com/software-development/cpp/threads/467086/stdfunction-with-several- veya-none-parameters # post2034402), ilgili olup olmadığından emin değil. – P0W

cevap

3

Düzenleme: Orijinal cevap, yanlış modifiye ama yine de iyi bir cevap olmayabilir eğitim amaçlı burada bırakarak:

Birçok değişken argüman fonksiyonları bir va_list sürümü var. printf örneğin vprintf sahiptir. Bu varyantlar, bir elips yerine açıkça bir va_list alır.

#include <iostream> 
#include <functional> 
#include <cstdarg> 


int main() 
{ 
    std::function<int(const char*,va_list)> test2(vprintf); 

    return 0; 
} 

Buna rağmen, bir acıdır. Orijinal yayınla ilgili sorun neydi

int invoke_variadic(const std::function<int(const char*,va_list)>& ref,const char* a ,...) 
{ 
    va_list args; 
    va_start(args,a); 
    ref(a,args); 
    va_end(args); 
} 

(teşekkürler /u/T.C.): Ben anlam aldı std::function<int(const char*,va_list)> test2(printf) derler, "çalıştı". Ancak, printf herhangi bir türdeki argümanları (va_list dahil) kabul edebileceğinden ve std::function sadece bu şekilde çağrılıp yapılamayacağını kontrol ettiği için derler. önerilen @MadScienceDreams Ne itibaren ardından

+0

Yani 'std :: function test2 (printf);' veya hatta std :: function test2 (printf) ; '. Derler çünkü "..." bir şeyle eşleşebilir, çünkü bir şekilde 'va_list' ile eşanlamlı değildir (kesinlikle değil). –

+0

@ T.C. Haklısın ... Bütün bunların neden derlediğini açıklayamıyorum. Hala ne olduğundan emin değilim, ama aslında bir va_list almıyor ... varolan bir printf varyantı var, ancak cevabımı yansıtacak şekilde değiştiriyorum. Bunu neden kabul ettiğine dair bir açıklama var mı? Aslında, giriş türlerini tanımladıktan sonra "iş" yapar ... – IdeaHat

+0

Bu, "printf" işlevini argüman listesiyle * çağırabildiğinizden ve "int" ile dolaylı olarak dönüştürülebilen bir şeyi geri alabildiğinizden dolayı çalışır. Yanlış biçim dizeleri vb. neden olduğu UB yok). 'std :: function', aslında saklandığı şeyin türünü umursamaz, sadece şablon parametresinde belirtilen şekilde çağrılabilir. –

0

, bu Birincisi ... benim için de oldukça

çalıştı, ben yapı içinde std değişken argüman versiyonlarını :: fonksiyon nesneleri tanımlanan, daha sonra gerçeği, kullanılan Bu C++ yanı bazı yöntemlerini eklemek için değil C: konsol çıkış için değişken argüman fonksiyonlarının

typedef struct { 
    std::function<void (void)> f1; 
    std::function<void (int)>  f2; 
    std::function<int (float *)> f3; 
    // ... and so on 

    std::function<int (const char * format, va_list args)> vprintToStdOut; 
    std::function<int (const char * format, va_list args)> vprintToStdErr; 

    int printToStdOut(const char * format, ...) 
    { 
     va_list ap; 
     va_start(ap, format); 
     int count = vprintToStdOut(format, ap); 
     va_end(ap); 
     return count; 
    } 

    int printToStdErr(const char * format, ...) 
    { 
     va_list ap; 
     va_start(ap, format); 
     int count = vprintToStdErr(format, ap); 
     va_end(ap); 
     return count; 
    } 

} CallbackTable; 

varsayılan uygulamaları, beyan ettikten sonra (daha sonra 'namespace std :: tutucuları kullanarak;' onsuz sözdizimi yönetilemez):

myCallbackTable.vprintToStdOut = std::bind(vfprintf, stdout, _1, _2); 
myCallbackTable.vprintToStdErr = std::bind(vfprintf, stderr, _1, _2); 

... ve bu noktadan itibaren, kullandığım umuyordum tam sözdizimi kullanabilirsiniz:

myCallbackTable.printToStdOut("I like to eat at least %d bananas a day\r\n", nBananas); 
İlgili konular