C++ 模板和定义的奇怪行为

C++ 模板和定义的奇怪行为,c++,templates,visual-studio-2008,syntax,c-preprocessor,C++,Templates,Visual Studio 2008,Syntax,C Preprocessor,我有以下定义: template<typename T1, typename T2> class Test2 { public: static int hello() { return 0; } }; template<typename T> class Test1 { public: static int hello() { return 0; } }; #define VERIFY_R(call) { if (call == 0) printf("

我有以下定义:

template<typename T1, typename T2>
class Test2
{
public:
    static int hello() { return 0; }
};

template<typename T>
class Test1
{
public:
    static int hello() { return 0; }
};

#define VERIFY_R(call) { if (call == 0) printf("yea");}
这是怎么回事? 这在VS2008SP1中发生

中的逗号被视为宏的参数分隔符,而不是模板的参数分隔符。因此,当只需要一个参数时,编译器认为您正在使用两个参数Test1::hello调用VERIFY\R。您需要使用展开提供给宏的所有内容:

#define VERIFY_R(...) { if ((__VA_ARGS__) == 0) printf("yea");}

通常,最好将宏参数用括号括起来,以防止出现其他奇怪的替换错误。

我不确定这是您报告中的错误还是实际问题,但您最后一次验证仍然引用Test1,预处理器是一个对C++一无所知的哑文本替换工具。它解释

VERIFY_R( Test1<int,int>::hello() );

然而,问题仍然是,为什么需要预处理器。您在问题中使用的宏也可以是内联函数。如果实际代码不需要预处理器,请尝试摆脱宏。它们只会引起疼痛

预处理器不知道应该是方括号,因此它将表达式解释为两个宏参数,Test1::hello,由分隔,。正如您所说,可以通过用括号包围整个表达式来解决这个问题,预处理器会将其识别为括号。

宏中的逗号可能不明确:第二个示例中的一组额外括号是消除歧义的一种方法。考虑宏

#define VERIFY(A, B) { if ( (A) && (B) ) printf("hi"); }
然后你可以写验证fooy

另一种消除歧义的方法是使用

typedef Test1<int,int> TestII;
VERIFY_R( TestII::hello() );

这可能是因为您在VERIFY\R中插入的任何内容都是按字面意思插入的。尝试将宏中的第二个调用更改为调用。这没有帮助,这是一个宏问题。有趣的是:这就是为什么BOOST_FOREACH会让新手头疼的原因:
#define VERIFY_R(...) { if ((__VA_ARGS__) == 0) printf("yea");}
VERIFY_R( Test1<int,int>::hello() );
VERIFY_R( (Test1<int), (int>::hello()) );
VERIFY_R( (Test1<int,int>::hello()) );
#define VERIFY(A, B) { if ( (A) && (B) ) printf("hi"); }
typedef Test1<int,int> TestII;
VERIFY_R( TestII::hello() );