6

I have some code that essentially condenses down to

#define FOO(a)
FOO(std::map<int, int>);

But it emits a compile error (too many actual parameters for macro FOO).

Obviously the preprocessor is thinking that I've supplied std::map<int and int> as arguments.

Is there a way round this? The preprocessor will not treat a quoted string with a comma in this way.

P45 Imminent
  • 8,319
  • 4
  • 35
  • 78
  • 1
    One easy way is to define a macro that resolves to comma. Another solution, when that's suitable, is to pass the template name and template arguments separately. However, I recall that Johannes Schaub had a neat trick for this that was more general. Now I'm just wringing my brain to try to remember it. No luck so far... :( – Cheers and hth. - Alf Sep 08 '15 at 14:42
  • Boss says I should just chill out and use a typedef. But that's rather boring. – P45 Imminent Sep 08 '15 at 14:44
  • How about [BOOST_PP_COMMA](http://stackoverflow.com/a/24793828/1708801) – Shafik Yaghmour Sep 08 '15 at 14:50
  • Does this answer your question? [Comma in C/C++ macro](https://stackoverflow.com/questions/13842468/comma-in-c-c-macro) – Evandro Coan Dec 15 '19 at 00:19
  • Does this answer your question? [How to pass multi-argument templates to macros?](https://stackoverflow.com/questions/8942912/how-to-pass-multi-argument-templates-to-macros) – Davis Herring Jul 03 '20 at 03:21

4 Answers4

4

The comma is being treated as a macro argument seperator, it does not do this with commas within parenthesizes.

If you are using Boost, they provide BOOST_PP_COMMA:

#include <boost/preprocessor/punctuation/comma.hpp>

#define FOO(a)
FOO(std::map<int BOOST_PP_COMMA int>);

You can also define your own:

#define COMMA ,
FOO(std::map<int COMMA int>);
Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
2

This should perhaps ideally be a comment, but SO doesn't support code in comments, so, you can do

#include <map>

#define T_ARGS( ... ) < __VA_ARGS__ >

#define FOO( a )  a x;

auto main() -> int
{
    FOO( std::map T_ARGS( int, int ) );
    (void) x;
}

or you can define a macro that resolves to comma, or you can use just about any scheme that's specific to some particular use case (e.g., passing template name separately).

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
2

Just add an extra set of parentheses:

#define FOO(a)
FOO((std::map<int, int>));
Simon Kraemer
  • 5,700
  • 1
  • 19
  • 49
1

The preprocessor will only treat unparenthesised commas as a macro argument separator. So what you can do is rewrite std::map<int, int> into something that has parentheses around it. A simple one might be decltype(std::map<int, int>()).