In C++17 with clang compiler, I get the same build errors whether I do this:
EXPECT_TRUE(std::is_same_v<decltype(var1), decltype(var2)>);
or this:
EXPECT_TRUE(typename std::is_same_v<decltype(var1), decltype(var2)>);,
or this:
EXPECT_TRUE(typename std::is_same_v<typename decltype(var1), typename decltype(var2)>);
Build command:
bazel test //my_target_dir:my_target
Build error:
error: too many arguments provided to function-like macro invocation decltype(var2)>); ^ gtest/gtest.h:1980:9: note: macro 'EXPECT_TRUE' defined here #define EXPECT_TRUE(condition) \ ^ myfile.cpp:125:5: error: use of undeclared identifier 'EXPECT_TRUE' EXPECT_TRUE(std::is_same_v< ^
Note that the Googletest definition for EXPECT_TRUE() is here: https://github.com/google/googletest/blob/master/googletest/include/gtest/gtest.h#L1980.
What is wrong with what I'm doing, and how can I get this to compile?
Summary
This does NOT work, because the C++ preprocessor which processes macros was written before templates existed, and sees the comma as separating two separate arguments to the macro. It thinks I have called the
EXPECT_TRUE()macro withanything<fooas the 1st argument, andbar>as the 2nd argument:These options DO work:
Details
After spending some time chatting with some friends, one of them, Drew Gross, explained the following:
He's spot-on correct. Since the C and C++ macro preprocessor was written PRIOR to C++ existing, it does not recognize the C++
<and>template scoping symbols (it thinks they are just "less than" and "greater than" symbols, respectively), so in this statement (EXPECT_TRUE(std::is_same_v<decltype(var1), decltype(var2)>);), it sees the comma and parsesstd::is_same_v<decltype(var1)as the 1st argument to the gtestEXPECT_TRUE()macro, anddecltype(var2)>as a 2nd argument to the macro.Therefore, here's the solution:
As Drew states, however, a better solution is to just use
static_assert()in this case instead of gtest'sEXPECT_TRUE(), since this test can be completed at compile-time rather than run-time:(better solution):
Note: message not required for
static_assert()in C++17. See here.I did some additional research and experimenting, and also discovered that extra parenthesis solve it too. Using extra parenthesis forces the preprocessor to recognize the whole input argument as 1 argument to the macro, since the preprocessor respects parenthesis but doesn't respect template
<>symbols at all since it isn't template-aware.Therefore, this works too:
If in doubt, parenthesize it out. If in need, parenthesis, indeed. :)
So, now we have 3 viable solutions to this problem. I'd probably go with the
static_assert()option as my primary solution, and the extra parenthesis option just above as my solution if I needed some template input to be tested during run-time.Additional References:
Once I knew what the nature of the problem was (the macro preprocessor seeing the comma and not recognizing C++ template
<and>scoping operators), I was able to do some Googling and find the following answers to look at too:Keywords: macro watch out for template parameter inputs; comma argument delimiter to C/C++ macro preprocessor, c++ extra parenthesis required in macros around macro parameters