ddesentz
ddesentz

Reputation: 1

Passing template parameters into macros in MSVC

I am trying to compile C++ code in Visual Studio 2017 that was originally developed on Linux. The project as is compiles on Linux but not in VS. The errors come from trying to use a macro to compare template parameters.

Call:

EXPECT_MATRIX_EQUAL(filter.xhat, mat);

Where 'filter.xhat' and 'mat' are both vectors

Defines:

#define EXPECT_MATRIX_EQUAL(...) \
NAVUTILS_TEST_MATRIX_EQUAL_(GTEST_NONFATAL_FAILURE_, __VA_ARGS__)

#define NAVUTILS_TEST_MATRIX_EQUAL_(fail, expected, actual, ...) \
NAVUTILS_TEST_EQUAL_(expected, \
                   actual,   \
                   __matrices_equal(expected, actual, ##__VA_ARGS__), \
                   fail)
#define NAVUTILS_TEST_EQUAL_(expected, actual, testExpr, fail) \
GTEST_TEST_BOOLEAN_(testExpr, #testExpr, actual, expected, fail) \
<< "Value of " #expected " [" << (expected).rows() << " x " << (expected).cols() << "]:\n" \
<< (expected) \
<< "\n\nValue of " #actual " [" << (actual).rows() << " x " << (actual).cols() << "]:\n" \
<< (actual)   \
<< "\n\n"

Errors:

C:\Users\ANTadmin\Desktop\scorpion-cpp\test\include\LinearFilterTests.h(19): warning C4003: not enough actual parameters for macro 'NAVUTILS_TEST_MATRIX_EQUAL_' 
C:\Users\ANTadmin\Desktop\scorpion-cpp\test\include\LinearFilterTests.h(19): error C2059: syntax error: ')' 
C:\Users\ANTadmin\Desktop\scorpion-cpp\test\include\LinearFilterTests.h(19): error C2181: illegal else without matching if 
C:\Users\ANTadmin\Desktop\scorpion-cpp\test\include\LinearFilterTests.h(19): error C2065: 'gtest_ar_': undeclared identifier 
C:\Users\ANTadmin\Desktop\scorpion-cpp\test\include\LinearFilterTests.h(19): error C2228: left of '.c_str' must have class/struct/union 
C:\Users\ANTadmin\Desktop\scorpion-cpp\test\include\LinearFilterTests.h(19): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'testing::internal::AssertHelper' 
C:\Users\ANTadmin\Desktop\scorpion-cpp\test\include\LinearFilterTests.h(19): note: No constructor could take the source type, or constructor overload resolution was ambiguous

I'm assuming there has to be something special with MSVC with how macros are used that I'm missing. From what I've researched the overloaded macros should be handled properly so I don't understand why I'm getting these errors.

Upvotes: 0

Views: 210

Answers (1)

rici
rici

Reputation: 241931

The main issue here is the way MSVC handles __VA_ARGS__ in a macro call inside a macro expansion. See this question and the answer which includes a statement from Microsoft about the interpretation of the standard. The solution, as suggested in the accepted answer to that question, is an extra level of indirection:

#define EXPAND_(X) X
#define EXPECT_MATRIX_EQUAL(...) \
EXPAND_(NAVUTILS_TEST_MATRIX_EQUAL_(GTEST_NONFATAL_FAILURE_, __VA_ARGS__))

There is also another issue:

__matrices_equal(expected, actual, ##__VA_ARGS__), \

That use of ## to avoid including the preceding , if __VA_ARGS__ is empty is a GCC extension and should not be used in portable code. However, apparently it works in MSVC.

Upvotes: 1

Related Questions