开发者

Problems with last recursion in metaprogramming

I have the following (partial) code in a class where I try to evaluate a value against a list of values via metaprogramming in 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 complains:

../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&)’

So it seems like it chokes on the last recursion when One has a value and Others don't. In this case the template parameters should then be empty. Do I need to declare the ordinary eval in another way? Haven't coded C++ in a while so it may be trivial but I just don't get it ;)

When trying to 开发者_运维技巧add template<> to the first eval it chokes:

../emul/GLPart.h:14:11: error: explicit specialization in non-namespace scope ‘class GLPart’ ../emul/GLPart.h:21:7: error: too many template-parameter-lists ../emul/GLPart.h: In member function ‘bool GLPart::Evaluate(GLenum)’: ../emul/GLPart.h:32:23: error: parameter packs not expanded with ‘...’: ../emul/GLPart.h:32:23: note: ‘ValidEnums’ ../emul/GLPart.h:32:33: error: expected ‘,’ or ‘;’ before ‘...’ token

Solution:

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);
};


As Bo Persson said, said, the first one is not a template, so calling eval will never call the first version. You want:

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);
};


Since this tends to produce lots of ambiguity errors, the variation that seems to work unambigously looks like this:

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);
};

The first overload takes exactly one argument, the second at least two. Taking zero arguments probably doesn't make sense anyway.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜