Шаблонная функция с двумя параметрами типа не скомпилируется при использовании с макросом проверки ошибок - PullRequest
0 голосов
/ 12 ноября 2011

Поскольку кто-то в нашей группе ненавидит исключения (давайте не будем обсуждать это здесь), мы склонны использовать макросы проверки ошибок в наших проектах C ++. Я столкнулся со странной ошибкой компиляции при использовании шаблонной функции с двумя параметрами типа. Есть несколько ошибок (ниже), но я думаю, что основной причиной является предупреждение:

warning C4002: too many actual parameters for macro 'BOOL_CHECK_BOOL_RETURN'

Вероятно, лучше всего объяснить в коде:

#include "stdafx.h"


template<class A, class B>
bool DoubleTemplated(B & value)
{
    return true;
}

template<class A>
bool SingleTemplated(A & value)
{
    return true;
}

bool NotTemplated(bool & value)
{
    return true;
}

#define BOOL_CHECK_BOOL_RETURN(expr) \
    do \
    { \
        bool __b = (expr); \
        if (!__b) \
        { \
            return false; \
        } \
    } while (false) \

bool call()
{
    bool thing = true;

//  BOOL_CHECK_BOOL_RETURN(DoubleTemplated<int, bool>(thing));
//  Above line doesn't compile.

    BOOL_CHECK_BOOL_RETURN((DoubleTemplated<int, bool>(thing)));
//  Above line compiles just fine.

    bool temp = DoubleTemplated<int, bool>(thing);
//  Above line compiles just fine.


    BOOL_CHECK_BOOL_RETURN(SingleTemplated<bool>(thing));
    BOOL_CHECK_BOOL_RETURN(NotTemplated(thing));

    return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
    call();
    return 0;
}

Вот ошибки, когда строка не закомментирована:

1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>Compiling...
1>test.cpp
1>c:\junk\temp\test\test\test.cpp(38) : warning C4002: too many actual parameters for macro 'BOOL_CHECK_BOOL_RETURN'
1>c:\junk\temp\test\test\test.cpp(38) : error C2143: syntax error : missing ',' before ')'
1>c:\junk\temp\test\test\test.cpp(38) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(41) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(48) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(49) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(52) : error C2143: syntax error : missing ';' before '}'
1>c:\junk\temp\test\test\test.cpp(54) : error C2065: 'argv' : undeclared identifier
1>c:\junk\temp\test\test\test.cpp(54) : error C2059: syntax error : ']'
1>c:\junk\temp\test\test\test.cpp(55) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(58) : error C2143: syntax error : missing ';' before '}'
1>c:\junk\temp\test\test\test.cpp(60) : error C2143: syntax error : missing ';' before '}'
1>c:\junk\temp\test\test\test.cpp(60) : fatal error C1004: unexpected end-of-file found
1>Build log was saved at "file://c:\junk\temp\test\test\Debug\BuildLog.htm"
1>test - 12 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Есть идеи? Спасибо!

Ответы [ 3 ]

2 голосов
/ 12 ноября 2011

Препроцессор имеет без понимания C ++ ! Он просто выполняет лексические замены.

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

Под скобками понимается PP как формирующая группу токенов, поэтому все, что находится внутри набора скобок, является одним большим токеном.

1 голос
/ 12 ноября 2011

Макросы не знают языка и работают только с лексическими токенами. Запятая разделяет аргументы для макроса, поэтому следующий код пытается «вызвать» макрос с двумя аргументами:

BOOL_CHECK_BOOL_RETURN(DoubleTemplated<int, bool>(thing));

DoubleTemplated<int и bool>(thing). Это предупреждение, которое вы видите, и причина других ошибок. Ниже приведен правильный способ защиты от , в списке аргументов шаблона:

BOOL_CHECK_BOOL_RETURN((DoubleTemplated<int, bool>(thing)));
1 голос
/ 12 ноября 2011

В строке, которая не компилируется, эта запятая интерпретируется препроцессором как разделитель аргументов макроса.

В стандарте C99 (у меня нет стандарта C ++, но он будет очень похож), в разделе 6.10.3 мы видим следующее:

Последовательность токенов предварительной обработки, ограниченная внешним Соответствующие скобки образуют список аргументов для функции, подобной макро. Отдельные аргументы в списке разделяются запятой токены предварительной обработки, но токены предварительной обработки через запятую внутренние скобки не разделяют аргументы.

Так вот почему ваш второй макрос работает.

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