2013-07-22 42 views
6

Şu anda, değişken şablon desteği ile yapabileceğim bazı şeylerin etrafından dolaşmaya çalışıyorum. Bu savların tamsayı olacak, ama belli ki başka bir şey sağlarsanız başarısız olacağını önceden varsaymak çünküC++ Bilinen Türlü Variadic İşlev Şablonları

template <typename ... Args> 
void foo(Args ... a) 
{ 
    int len = sizeof...(tail); 
    int vals[] = {a...}; 
    /* Rest of function */ 
} 

/* Elsewhere */ 
foo(1, 2, 3, 4); 

Bu kod çalışır - ı böyle bir işlevi var diyelim. Ben parametre paketleri önceden belli türünü içeren biliyorum, ben gibi bir şey çiftleşmiş olmadan ve olabilir bir yol var mı -

void foo(int ... a) 

bunu yaparken denedi, ama derleyici bir hata verdi Bir boşluk alanı olan foo hakkında. Biliyorum ki, paket içerisindeki parametrelere özyinelemeyle de erişebiliyorum, ancak bunun sahip olduğum problemi çözeceğinden emin değilim - yani aynı türden değişken bir argüman numarası almak istiyorum. Daha önce türlerini biliyorsanız

+1

Sen her türlü * * int olduğundan emin olmak için 'enable_if' kullanabilirsiniz. –

+2

Kod, bir grup ints'e daldığınızda çalışır. Başka bir şey verirsen işe yaramaz. Görev yerine getirilmiş gibi görünüyor. Sorun nerede? –

+0

Sanırım sorun, derleme zamanında ints olduklarının garanti edilip edilmeyeceğidir. – znby

cevap

3

, sen std:initializer_list ile fonksiyon aşırı kullanabilirsiniz:

#include <initializer_list> 
#include <iostream> 

void foo(std::initializer_list<int> l) 
{ 
    for (auto el : l) 
     // do something 
} 

void foo(std::initializer_list<float> l) 
{ 
} 

void foo(std::initializer_list<std::string> l) 
{ 
} 

int main() 
{ 
    foo({1, 2, 3, 4 }); 
    foo({1.1f, 2.1f, 3.1f, 4.1f }); 
    foo({ "foo", "bar", "foo", "foo" }); 
    return 0; 
} 

Visual Studio 2012 kullanıyorsanız, Visual C++ Compiler November 2012 CTP gerekebilir.

DÜZENLEME:

template <int ... Args> 
void foo() 
{ 
    int len = sizeof...(Args); 
    int vals[] = {Args...}; 
    // ... 
} 

// And 

foo<1, 2, 3, 4>(); 

Ama bunun float ve örneğin std::string ile çalışmadığını hatırlamak zorunda: Hala variadic şablonu kullanmak istiyorsanız, yapabileceğiniz Eğer 'float': illegal type for non-type template parameter ile sona erecek . float, non-type template parameter numaralı telefondan yasal değildir, bu hassaslıkla ilgilidir, kayan noktalı sayılar tam olarak gösterilemez ve aynı türden söz etmenin olasılığı sayının nasıl temsil edildiğine bağlı olabilir.

+0

Derleme zamanında argüman sayısını bilmeniz gerekiyorsa, bu geçici çözüm yeterli değildir, çünkü 'initializer_list' bir constexpr size()' elemanı sağlamamaktadır. AFAIK, 'is_same <>/is_convertible <>' kontrolleri ile variadic şablonlar arasında bir yol yoktur. – user2523017

+0

@ user2523017 Haklısınız, bu çözümle derleme zamanında argüman sayısına sahip olamayız. –

1

Şu anda, variadic şablon desteğiyle yapabileceğim bazı şeylerin etrafından dolaşmaya çalışıyorum.

sorununuz için herhangi çözüm, sonra aşağıdaki koda bakmanızı öneririm bulmak, variadic şablonlarla değil denemek istiyorsanız varsayarsak:

#include <iostream> 

template<int ...Values> 
void foo2() 
{ 
    int len = sizeof...(Values); 
    int vals[] = {Values...}; 

    for (int i = 0; i < len; ++i) 
    { 
     std::cout << vals[i] << std::endl; 
    } 
} 

int main() 
{ 
    foo2<1, 2, 3, 4>(); 

    return 0; 
} 

foo2 arasındaki fark senin foo, parametreleri çalışma zamanında foo'a ve derleme zamanında foo2'a iletmenizdir, böylece kullandığınız her parametre kümesi için derleyici ayrı foo2 işlev gövdesi oluşturur.

10

Bu çalışması gerekir:

void foo(int); 

template<typename ...Args> 
void foo(int first, Args... more) 
{ 
    foo(first); 
    foo(std::forward(more)...); 
} 
+0

Bu cevap, OP'nin sorduğu şey için daha uygun. Bu çözümün tek dezavantajı, yineleme kısmıdır. Ama şimdi C++ 17 ve katlama ifadeleri kullanarak bile daha iyi bir çözüm görebiliyorum. – mic

İlgili konular