Проблемы с последней рекурсией в метапрограммировании - PullRequest
0 голосов
/ 20 августа 2011

У меня есть следующий (частичный) код в классе, где я пытаюсь оценить значение по списку значений с помощью метапрограммирования в 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: в функции-члене ‘bool GLPart :: eval (GLenum) [с неподписанным 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: создается из ‘bool GLPart :: eval (GLenum) [с неподписанным 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: создается из ‘bool GLPart :: eval (GLenum) [с неподписанным int One = 517u, unsigned int ... Others = {518u, 519u}, unsigned int ... ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = без знака int] ’../emul/GLPart.h:26:31: создается из‘ bool GLPart :: eval (GLenum) [с неподписанным int One = 516u, unsigned int ... Другие = {517u, 518u, 519u}, unsigned int ... ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int] ’../emul/GLPart.h:26:31: создается из ‘Bool GLPart :: eval (GLenum) [с беззнаковым int One = 515u, unsigned int ... Другие = {516u, 517u, 518u, 519u}, unsigned int ... ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int] ’../emul/GLPart.h:26:31: создается из ‘Bool GLPart :: eval (GLenum) [с беззнаковым int One = 514u, unsigned int ... Другие = {515u, 516u, 517u, 518u, 519u}, unsigned int ... ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int] ’../emul/GLPart.h:26:31: создается из ‘Bool GLPart :: eval (GLenum) [с беззнаковым int One = 513u, unsigned int ... Другие = {514u, 515u, 516u, 517u, 518u, 519u}, без знака int ... ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int] ’../emul/GLPart.h:26:31:
создается из ‘bool GLPart :: eval (GLenum) [с unsigned int One = 512u, unsigned int ... Другие = {513u, 514u, 515u, 516u, 517u, 518u, 519u}, без знака int ... ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int] ' ../emul/GLPart.h:31:43: создается из ‘bool GLPart :: Evaluate (GLenum) [с неподписанным int ... ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = без знака int] ’alpha.cpp: 8: 7: создается здесь ../emul/GLPart.h:26:31: ошибка: нет соответствующей функции для вызова ‘GLPart <512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u> :: eval (GLenum &) ’

Похоже, что последняя рекурсия задыхается, когда Один имеет значение, а Другие нет. В этом случае параметры шаблона должны , тогда будут пустыми. Нужно ли объявлять обычный eval по-другому? Давно не кодировал C ++, так что это может быть тривиально, но я просто не понимаю;)

При попытке добавить template <> к первому eval, он задыхается:

.. / emul / GLPart.h: 14: 11: ошибка: явная специализация в область без пространства имен "class GLPart" ../emul/GLPart.h:21:7: ошибка: слишком много списков параметров-шаблонов ../emul/GLPart.h: внутри пользователя Функция «bool GLPart :: Evaluate (GLenum)»: ../emul/GLPart.h:32:23: ошибка: пакеты параметров не расширены ‘...’: ../emul/GLPart.h:32:23: примечание: «ValidEnums» ../emul/GLPart.h:32:33: ошибка: ожидается ‘,’ или ‘;’ до маркера ‘...’

Решение:

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

Ответы [ 2 ]

3 голосов
/ 20 августа 2011

Как сказал Бо Перссон, первый не является шаблоном, поэтому вызов 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);
};
2 голосов
/ 21 августа 2011

Так как это приводит к множеству ошибок неоднозначности, вариант, который работает однозначно, выглядит следующим образом:

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

Первая перегрузка принимает ровно один аргумент, а вторая - не менее двух. Принятие нулевых аргументов, вероятно, в любом случае не имеет смысла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...