pass method with template arguments to a macro
Asked Answered
P

4

25

I am unable to use Google Test's ASSERT_THROW() macro in combination with multiple template arguments. Consider that I want to make sure that construction of Matrix<5,1> throws:

ASSERT_THROW(Matrix<5,1>(), std::runtime_error);

(this example doesn't make a lot of sense, of course this shoud not throw, but it is what stayed after simplifying what I had.)

I get this output from MS VC++ 2008:

warning C4002: too many actual parameters for macro 'ASSERT_THROW'
error C2143: syntax error : missing ',' before ';'

Whereas there are no problems with:

ASSERT_THROW(Matrix<1>(), std::runtime_error);

How can I overcome this problem?

Thanks!

Photography answered 21/12, 2010 at 6:42 Comment(1)
Dupe? #4296390 (asked one month before this one)Sappy
I
26

the problem is the extra comma, you will need to protect it from the macro. Try

ASSERT_THROW((Matrix<5,1>()), std::runtime_error);
Inamorato answered 21/12, 2010 at 6:56 Comment(3)
This works only if Matrix<5,1>() used in an expression... So it works here and simpler than mine. +1Scaliger
What exactly are all the things that protect commas in macros? For now I know parenthesis (1,1) (from this answer) and double quotes "1,1" (from tests). Where / what is the full list?Sappy
This is defined in the C standard (section 6.10.3 of my copy of the C99 draft): The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments. If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives,150) the behavior is undefined.Inamorato
S
25
#define COMMA ,
ASSERT_THROW(Matrix<5 COMMA 1>(), std::runtime_error);

Edit: @tletnes answer is simpler, however this one will work even if the macro parameter used as a non-expression. For example:

BOOST_FOREACH(std::pair<int COMMA int>& v, myVec) { } // works
BOOST_FOREACH((std::pair<int, int>)& v, myVec) { } // fails

More edit: The macro COMMA is already defined in boost:

#include <boost/preprocessor/punctuation/comma.hpp>
ASSERT_THROW(Matrix<5 BOOST_PP_COMMA() 1>(), std::runtime_error);
BOOST_FOREACH(std::pair<int BOOST_PP_COMMA() int>& v, myVec) { }
Scaliger answered 21/12, 2010 at 6:55 Comment(1)
BOOST_PP_COMMA() seems to work more reliably across situations than the other methods. Thanks for the tip!Sylvia
O
12

#define COMMA , may not compile in GCC. Use #define COMMA() , instead. Why can't I add comment to other's post?

Ovaritis answered 21/12, 2010 at 7:53 Comment(3)
good point, thanks. You need some reputation for adding comments.Photography
If you use the simple COMMA in complex macros, such as a REPEAT, it won't compile on GCC. boost library also use COMMA(). See boost/preprocessor/punctuation/comma.hpp. I've ever used COMMA, not compile on mingw32-g++.exe 4.4.0Ovaritis
PS: For simple use, such as your another reply, it may work fine. But I really felt headache when the simple COMMA won't compile in complex macros. :-)Ovaritis
A
1

In addition to the answers posted, you could also try

using ColVector5f = Matrix<5,1>;
ASSERT_THROW(ColVector5f(), std::runtime_error);

So that the preprocessor doesn't get confused by the comma.

Anemic answered 25/1, 2022 at 19:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.