当std :: map存在时,宏将代码语句作为参数失败

时间:2014-04-25 12:13:34

标签: c++ visual-studio visual-c++ c-preprocessor visual-studio-macros

我在代码语句周围使用了一个宏来引入嵌套异常处理:

#define TRAP_EXCEPTION(statement) \
    try \
    { \
        try{statement} \
        catch(Engine::Exception& e) \
        { \
            throw MyException(e.message()); \
        } \
    }

在一个案例引发编译器错误之前,这一直运行良好。我设法构建了一个最小的例子:

TRAP_EXCEPTION
(
 std::map<MyType, bool> Map;
)
catch(MyException& e)
{
}

这会产生以下错误......我该如何修复它(理想情况下在宏中)?

> error C2143: syntax error : missing '>' before '}'
> error C2976: 'std::map' : too few template arguments
> error C2143: syntax error : missing ';' before '}'

3 个答案:

答案 0 :(得分:5)

宏不理解模板参数(尖括号是精确的),他们只看到,并认为你为宏提供了两个不同的参数。您需要添加圆括号:

TRAP_EXCEPTION
(
    (std::map<MyType, bool> Map;)
)

并且需要更改宏:

#define UNWRAP(...) __VA_ARGS__

#define TRAP_EXCEPTION(statement) \
    try \
    { \
        try{UNWRAP statement} \
        catch(Engine::Exception& e) \
        { \
            throw MyException(e.message()); \
        } \
    }

请注意,这需要您始终在通话方提供一对额外的圆括号。

在你的情况下(因为宏只应该只有一个语句),你也可以使用一个可变参数宏:

#define TRAP_EXCEPTION(...) \
    try \
    { \
        try{ __VA_ARGS__ } \
        catch(Engine::Exception& e) \
        { \
            throw MyException(e.message()); \
        } \
    }

这可能更好,因为呼叫方没有改变和

TRAP_EXCEPTION
(
    std::map<MyType, bool> Map;
)

现在可以正常使用。

答案 1 :(得分:3)

预处理器不会将<>识别为括号,因此将逗号解释为宏参数分隔符。如果语句因任何其他原因包含未加括号的逗号(例如逗号运算符或逗号分隔声明符),则会出现同样的问题。

如果你真的想滥用这样的预处理器,你可以提出它接受任意数量的宏参数:

#define TRAP_EXCEPTION(...) \
try \
{ \
    try{__VA_ARGS__} \
    catch(Engine::Exception& e) \
    { \
        throw MyException(e.message()); \
    } \
}

但我建议你不要尝试用宏做任何聪明的事。

答案 2 :(得分:3)

您可以在宏之前使用typedef,而不是__VA_ARGS__技巧。 __VA_ARGS__技巧有一些缺点。

typedef std::map<MyType, bool> MyMap;

TRAP_EXCEPTION(
  MyMap Map;
)