2012-04-06 9 views
19

Zaten örneğin here ele alındığı gibi, c değişkeni bağımsız değişken ++ olan bir işlev için stdarg.h yol biliyorum. Ayrıca biliyorum C++ 11 standart here açıklandığı gibi variadic şablonları vardır. bilinen türde bağımsız değişken ile yapılan bir fonksiyonu, C++ 11 yolu

Ama biz bilmiyoruz (ve biz zorlayamaz) afaik derleme zamanında argüman türleri yukarıda belirtilen iki şema içinde

. Aradığım şey, bilinen tür değişken değişkenlerini bir işleve aktarmaktır. onlar kısıtlamalar empoze yok çünkü genellikle daha iyi bir seçimdir, aynı zamanda bağımsız değişken sayısı almak işlevler oluşturmak için kullanılabilir

Değişkin şablonları: Ben bunun here hakkında okuyun çünkü bu yapılabilir düşünüyorum argüman türleri, integral ve kayar nokta promosyonları gerçekleştirmeyin ve güvenli yazın.

Mümkün mü? Eğer evet ise, bunu nasıl yapabilirim? Değişken parametreler tek türdeki tüm iseniz

cevap

30

argümanların rastgele sayı kabul variadic şablonları içeren bir işlev yazmak için yalındır. Genel paternin tek farkı, bir şablon parametresi yerine ilk argüman (kafa) olarak bir beton tipinin kullanılmasıdır. Aşağıdaki örnek, rasgele bir dizi dizeyi kabul eden foobar işlevini gösterir.

// used for end of recursion - and for the empty arguments list 
void foobar() { } 

template <typename ...Tail> 
void foobar(const std::string& head, Tail&&... tail) 
{ 
    // do something with head 
    std::cout << head << '\n'; 
    // call foobar recursively with remaining arguments 
    foobar(std::forward<Tail>(tail)...); 
} 

foobar("Hello", "World", "..."); 

Şahsen, variadic şablonlar yerine std::initializer_list kullanmayı tercih ediyoruz. Variadic şablonlar daha karmaşık olduğundan ve ek deneyim gerektirdiğinden. std::initializer_list ile, bu gibi görünebilir:

void foobar(std::initializer_list<std::string> values) 
{ 
    for (auto& value : values) { 
     // do something with value 
     std::cout << value << '\n'; 
    } 
} 

foobar({ "Hello", "World", "...", }); 

Maalesef ek küme parantezleri gerekli olan düzenli fonksiyonları ile std::initializer_list kullanırken. Yeni başlatıcı sözdizimi kullanılırsa, kurucular için gerekli değildir.

Düzenleme: Rewrote geribildirim göre cevap. Özellikle iki çözümün/örneklerin sırasını değiştirdim.

+1

Sanırım her şey yanlış anlaşılmadı. İkinci yolu biliyordum, ama her zaman, parametrelerin türü üzerinde kontrol olmadığını düşündüm. Bu doğru değil. işlev, bilinen bir türün ilk parametresini aldığından (burada dizgi), bu türdeki parametrelere sahip olması zorunludur. Teşekkür ederim. – melmi

+2

İlk önce ikinci kod kutusunu taşımak isteyebilirsiniz. 'Initializer_list' sürümü değilken, problem için çok iyi bir çözüm. SFINAE ile böyle büyük, karmaşık bir şey yayınlayacaktım, ama bu çok daha mantıklı. –

+0

böyle, std :: initializer_list sürümü etrafında variadic şablon sarmalayıcı oluşturarak, std :: initializer_list ve variadic şablon yaklaşım hem karıştırın eğer gerçekten küme parantezi kullanarak kaçınabilir @nosid: (http [coliru görmek]: //coliru.stacked-crooked.com/a/4baef67192a0310c). –

2

, sen '...' bu tür bir dizi çekmek yerine kullanarak işlev imzayı değiştirebilir.

+0

Değişken işlevlerin kullanımı, derleme zamanı satır içi mekanizması sağlarken, bir türden bir dizi yinelemeye ihtiyaç duyar. Bir dizide döngü yapmanın o kadar zaman harcadığını söyleyebilirsiniz, ancak bunu başka bir çok büyük döngüde düşünün. – melmi