2つの型パラメータを持つテンプレート関数は、エラーチェックマクロとともに使用するとコンパイルに失敗する

私たちのグループの誰かが例外を嫌うので(ここで議論しません)、C ++プロジェクトでエラーチェックマクロを使用する傾向があります。 2つの型パラメータを持つテンプレート関数を使用すると、奇妙なコンパイルエラーが発生しました。いくつかのエラー(下記)がありますが、根本的な原因は警告だと思います。

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

おそらくコードで最もよく説明されています:

#include "stdafx.h"


template
bool DoubleTemplated(B & value)
{
    return true;
}

template
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(thing));
//  Above line doesn't compile.

    BOOL_CHECK_BOOL_RETURN((DoubleTemplated(thing)));
//  Above line compiles just fine.

    bool temp = DoubleTemplated(thing);
//  Above line compiles just fine.


    BOOL_CHECK_BOOL_RETURN(SingleTemplated(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 ==========

何か案は?ありがとう!

0
追加された
ビュー: 1
その特定の人を撃つか、少なくとも上司の娘と不倫を抱いているために彼を選ぶことは選択肢ですか?
追加された 著者 Kerrek SB,
@ KerrekSB - ハハ:)
追加された 著者 SirPentor,

3 答え

プリプロセッサに C ++についての理解がないがあります。これは単に字句置換を実行します。

複数引数のマクロを宣言すると、引数はカンマで区切られます。マクロの呼び出しにカンマがあるので、1つの引数しか取らないと宣言されているにもかかわらず、複数のパラメータでマクロを呼び出すことになります。

括弧は、PPによってトークングループを形成するものとして理解されるため、括弧内のすべてが大きなトークンです。

2
追加された

マクロはその言語を認識せず、レキシカルトークンのみで動作します。マクロの引数をカンマで区切ると、次のコードでは2つの引数を指定してマクロを呼び出すよう試みます。

BOOL_CHECK_BOOL_RETURN(DoubleTemplated(thing));

DoubleTemplated and bool>(thing). That's the warning you are seeing, and cause of the other errors as well. The following is the correct way to protect against , in template arguments list:

BOOL_CHECK_BOOL_RETURN((DoubleTemplated(thing)));
1
追加された

コンパイルされない行では、そのコンマはプリプロセッサによってマクロ引数の区切り文字として解釈されます。

C99標準では(私はC ++の標準を手に入れることはできませんでしたが、それは非常に似ています)、6.10.3節で以下を参照してください:

最外部で囲まれた前処理トークンのシーケンス   括弧が一致すると、関数のような引数のリストが作成されます   マクロ。リスト内の個々の引数はコンマで区切られています   トークンを前処理するが、マッチングの間にトークンをカンマで前処理する   内側の括弧は引数を区切っていません。

それで、あなたの2番目のマクロインスタンス生成が機能します。

1
追加された