2011-08-20 4 views
0

C++ 11でメタプログラミングを使用して値のリストに対して値を評価しようとするクラスに、次の(部分的な)コードがあります。メタプログラミングでの最後の再帰に関する問題

bool eval(GLenum value) 
{ 
    return false; 
}; 

template<GLenum One, GLenum... Others> 
bool eval(GLenum value) 
{ 
    if(value == One) 
     return true; 

    // Try out the rest 
    return eval<Others...>(value); 
}; 

gccが文句を言う:

../emul/GLPart.h: In member function ‘bool GLPart::eval(GLenum) [with unsigned int One = 519u, unsigned int ...Others = {}, unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’: ../emul/GLPart.h:26:31: instantiated from ‘bool GLPart::eval(GLenum) [with unsigned int One = 518u, unsigned int ...Others = {519u}, unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’ ../emul/GLPart.h:26:31: instantiated from ‘bool GLPart::eval(GLenum) [with unsigned int One = 517u, unsigned int ...Others = {518u, 519u}, unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’ ../emul/GLPart.h:26:31: instantiated from ‘bool GLPart::eval(GLenum) [with unsigned int One = 516u, unsigned int ...Others = {517u, 518u, 519u}, unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’ ../emul/GLPart.h:26:31: instantiated from ‘bool GLPart::eval(GLenum) [with unsigned int One = 515u, unsigned int ...Others = {516u, 517u, 518u, 519u}, unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’ ../emul/GLPart.h:26:31: instantiated from ‘bool GLPart::eval(GLenum) [with unsigned int One = 514u, unsigned int ...Others = {515u, 516u, 517u, 518u, 519u}, unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’ ../emul/GLPart.h:26:31: instantiated from ‘bool GLPart::eval(GLenum) [with unsigned int One = 513u, unsigned int ...Others = {514u, 515u, 516u, 517u, 518u, 519u}, unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’ ../emul/GLPart.h:26:31:
instantiated from ‘bool GLPart::eval(GLenum) [with unsigned int One = 512u, unsigned int ...Others = {513u, 514u, 515u, 516u, 517u, 518u, 519u}, unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’ ../emul/GLPart.h:31:43: instantiated from ‘bool GLPart::Evaluate(GLenum) [with unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’ alpha.cpp:8:7: instantiated from here ../emul/GLPart.h:26:31: error: no matching function for call to ‘GLPart<512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u>::eval(GLenum&)’

一つはにはない価値とその他を持っているとき、それは最後の再帰にチョークのようなので、それはそう。この場合、テンプレートパラメータとなるはずです。別の方法で通常の評価を宣言する必要がありますか?

​​

が、それはチョーク最初のevalにテンプレート<>を追加しようとした場合)、それは些細なことかもしれないが、私はちょうどそれを得ることはありませんので、しばらくC++をコーディングしていませんソリューション:

template<GLenum One> 
bool eval(GLenum value) 
{ 
    return value == One; 
}; 

template<GLenum One, GLenum Two, GLenum... Others> 
bool eval(GLenum value) 
{ 
    if(eval<One>(value)) 
     return true; 

    // Try out the rest 
    return eval<Two, Others...>(value); 
}; 
+1

[これらの2つの可変機能の本質的な違いは何ですか?](http://stackoverflow.com/questions/7111089/whats-the-essential-difference-between-the-two-variadic-functions) –

+4

最初の関数はテンプレートではないので、 'eval (value);'のように呼び出すことはできません。 –

+0

試しましたが、別のエラーを作成しました... – abergmeier

答えて

2

これは曖昧エラーの多くを生成する傾向があるので、unambigously動作しているようですばらつきが次のようになります。

template<GLenum One> 
bool eval(GLenum value) 
{ 
    return value == One; 
}; 
template<GLenum One, GLenum Two, GLenum... Others> 
bool eval(GLenum value) 
{ 
    if(value == One) 
     return true; 

    // Try out the rest 
    return eval<Two, Others...>(value); 
}; 

最初のオーバーロードは、少なくとも正確に一つの引数、秒を要します二。とにかくゼロ引数を取ることはおそらく意味がありません。

+0

これは確かに動作します。これは、Bo Perssonが言及した関数テンプレート_非常に優雅に_specializingする問題を防ぎます。 – abergmeier

3

ボーPerssonのが言ったように、最初のものは、テンプレートではありませんので、evalのを呼び出すと、最初のバージョンを呼び出すことはありません、と述べました。あなたが欲しい:

template<> //this tells compiler that eval is a template function 
bool eval(GLenum value) 
{ 
    return false; 
}; 
template<GLenum One, GLenum... Others> 
bool eval(GLenum value) 
{ 
    if(value == One) 
     return true; 

    // Try out the rest 
    return eval<Others...>(value); 
}; 
+0

私はあなたもこれを行うことはできませんと思います。問題は、関数テンプレート、クラステンプレートだけを特化することができないということです。呼び出しが 'eval(value)'であっても 'eval (value)'でなかった場合にはうまくいったかもしれません。 –

+0

興味深いことに、これはWikipediaの例です:) http://en.wikipedia.org/wiki/C%2B%2B0x#Variadic_templates – abergmeier

+0

しかし、Wikipediaには型引数(値引数ではありません)がありますので、呼び出しは引数型の控除に依存します過負荷の分解能。 – UncleBens