There are situations in which the cpp wrongly takes commas separating
template arguments as macro arguments delimiters.
But the issue only arises in C++, and the preprocessor is already different.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
> To post to this group, send email to std-pr...@isocpp.org.
> Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
On 2015–10–09, at 12:20 PM, dgutson . <daniel...@gmail.com> wrote:There are situations in which the cpp wrongly takes commas separating
template arguments as macro arguments delimiters.
For example:
template <class X, class Y> struct S;
#define Macro(arg) S arg;
The extra ( ) workaround used in C cannot be used here:
Macro((<int, int>));
This is important for X-macros for example.
I propose to enhance the cpp to be able to ignore escaped commas (with
\), so this can be done:
Macro(<int\, int>);
We already implemented this extension in gcc (patch to be sent on
Monday) which is working.
What we did is: comma escaping occurs at the top level, but not inside ( ).
For example
SomeMacro(f(a\,b))
does no escape the comma and thus has current behavior.
I think I still prefer solutions A and B.
#define ARG(...) __VA_ARGS__Macro(ARG(<int, int>))On 2015–10–09, at 12:20 PM, dgutson . <daniel...@gmail.com> wrote:There are situations in which the cpp wrongly takes commas separating
template arguments as macro arguments delimiters.
For example:
template <class X, class Y> struct S;
#define Macro(arg) S arg;
The extra ( ) workaround used in C cannot be used here:
Macro((<int, int>));Solution A:#define EXPAND( ARG ) ARG#define Macro( ARG ) S EXPAND ARGMacro((<int, int>))Solution B:#define Macro( ... ) S __VA_ARGS__Macro(<int, int>)Solution C:#define COMMA ,Macro(<int COMMA int>)
On 2015–10–09, at 5:20 PM, Lingxi Li <lilin...@gmail.com> wrote:How about defining a general grouping macro like#define ARG(...) __VA_ARGS__
So, the usage would beMacro(ARG(<int, int>))
On 2015–10–09, at 5:28 PM, Roman Perepelitsa <roman.pe...@gmail.com> wrote:The implementation of UNPARENTHESIZE_IF_PARENTHESIZED is non-trivial.
I believe it also requires a compiler extension (the last one in https://gcc.gnu.org/onlinedocs/gcc/Variadic-Macros.html#Variadic-Macros).
It's possible to writing macros that behave well in the presence of arguments with commas. It's just hard.
#define TERNARY(a, b, c) ...TERNARY(UNPARENTHESIZE_IF_PARENTHESIZED(...), UNPARENTHESIZE_IF_PARENTHESIZED(...), UNPARENTHESIZE_IF_PARENTHESIZED(...))On 2015–10–09, at 5:20 PM, Lingxi Li <lilin...@gmail.com> wrote:How about defining a general grouping macro like#define ARG(...) __VA_ARGS__
So, the usage would beMacro(ARG(<int, int>))This macro is what I meant to say for solution A. The approach is very similar, call it A’. Any macro expecting a template argument list might take a parenthesized argument as a courtesy. For surprising cases you can DIY.On 2015–10–09, at 5:28 PM, Roman Perepelitsa <roman.pe...@gmail.com> wrote:The implementation of UNPARENTHESIZE_IF_PARENTHESIZED is non-trivial.Please, do share.
I believe it also requires a compiler extension (the last one in https://gcc.gnu.org/onlinedocs/gcc/Variadic-Macros.html#Variadic-Macros).I’ve proposed this for standardization in N4220. Unfortunately, it’s not been reviewed.It's possible to writing macros that behave well in the presence of arguments with commas. It's just hard.It’s hard to optionally strip parens automatically. It’s easy to expect one level of parens and strip them. It’s also easy to use __VA_ARGS__, albeit ugly.Bah, my cursed brain went and solved the riddle. I don’t see any need for an extension.#define UNPAREN(...) UNPAREN __VA_ARGS__
#define DONE_UNPAREN
#define CAT_LIT(A, ...) A ## __VA_ARGS__
#define CAT(A, ...) CAT_LIT( A, __VA_ARGS__ )
#define UNPARENTHESIZE_IF_PARENTHESIZED(...) CAT( DONE_, UNPAREN __VA_ARGS__ )I’d almost call this trivial. CAT/CAT_LIT is a common utility needed for any preprocessor metaprogramming.
I fail to see the point in implementing this UNPARENTHESIZE_IF_PARENTHESIZED thing. The original goal is to pass argument containing commas as a single argument. So, suppose there is a function macro that takes three arguments#define TERNARY(a, b, c) ...
So how could UNPARENTHESIZE_IF_PARENTHESIZED help with this goal?TERNARY(UNPARENTHESIZE_IF_PARENTHESIZED(...), UNPARENTHESIZE_IF_PARENTHESIZED(...), UNPARENTHESIZE_IF_PARENTHESIZED(...))
Like this? If so, I don't think it is any better than my ARG macro, except that it is much more complex. Or you mean to implement the trick for every function macro that wants this functionality? I don't think there would be many people thinking that it's worth the effort.
On 2015–10–09, at 9:50 PM, Roman Perepelitsa <roman.pe...@gmail.com> wrote:
// Requires Boost.Preprocessor.#include "boost/boost/preprocessor.hpp"// Expands to 1 if called without args. Otherwise expands to 0.// I believe this can't be implemented in pure C or C++ without extensions.#define IS_EMPTY(...) IS_EMPTY_I(__VA_ARGS__)#define IS_EMPTY_I(...) \BOOST_PP_EQUAL(1, BOOST_PP_VARIADIC_SIZE(_, ##__VA_ARGS__))// Expands to 1 if the input is parenthesized. Otherwise expands to 0.#define IS_PARENTHESIZED(...) IS_EMPTY(BOOST_PP_EAT __VA_ARGS__)// If the input is parenthesized, removes the parentheses. Otherwise expands to// the input unchanged.#define UNPARENTHESIZE_IF_PARENTHESIZED(...) \BOOST_PP_IF(IS_PARENTHESIZED(__VA_ARGS__), BOOST_PP_REM, \BOOST_PP_EMPTY()) \__VA_ARGS__Note that I'm not an expert in preprocessor. I came up with this macro when I needed it, and it works fine for my use cases. It might have flaws that I don't see, and there might be a simpler implementation.
This implementation removes leading parentheses: UNPARENTHESIZE_IF_PARENTHESIZED((int)42) expands to `int 42`, while we need `(int)42`.
On 2015–10–13, at 4:01 PM, Bengt Gustafsson <bengt.gu...@beamways.com> wrote:The problem with all of these approaches is that it gets more or less noisy at the call site.
What are the remaining use cases where this would not work?
Why not:
#deffun MY_DECLARATION(A, B)
...and perform argument splitting as if MY_DECLARATION were a regular
C++ function and not a macro? This would preclude feeding it arguments
--
Matthew
Why is this so hard? I can write this as a C proposal as a last resort. But the C++ preprocessor is already different than the C one, I still don't understand the 'go to C first' specially considering that this problem does not affect to C, why would they even care?
So what was the history regarding the // comments? That's the first historic difference that comes to my mind now.
On 2015–10–14, at 12:01 AM, dgutson . <daniel...@gmail.com> wrote:Why is this so hard? I can write this as a C proposal as a last resort. But the C++ preprocessor is already different than the C one
So what was the history regarding the // comments? That's the first historic difference that comes to my mind now.
On Tuesday 13 October 2015 14:38:11 dgutson . wrote:
> > C99 added // comments. But, comments are part of lexing.
>
> I know about C99, but I'm asking for the history behind the // : how
> was that added at that time?
By changing the C preprocessor to accept it too. You may remember that even in
C89 mode, most C compilers accept // comments, unless they've been placed in
strict C89 mode.
So, yes, you can turn some features on and off in the preprocessor.
El 13/10/2015 15:47, "Thiago Macieira" <thi...@macieira.org> escribió:
>
> On Tuesday 13 October 2015 14:38:11 dgutson . wrote:
> > > C99 added // comments. But, comments are part of lexing.
> >
> > I know about C99, but I'm asking for the history behind the // : how
> > was that added at that time?
>
> By changing the C preprocessor to accept it too. You may remember that even in
> C89 mode, most C compilers accept // comments, unless they've been placed in
> strict C89 mode.
Ok, I see, the problem with this is that this is a C++-only thing (wereas the // was a useful addition for C), so there's no reason the C Committee could be interested in accepting it, so I foresee a dead end in that way. Is your advise to still try it anyway?
>
> So, yes, you can turn some features on and off in the preprocessor.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
There are situations in which the cpp wrongly takes commas separating
template arguments as macro arguments delimiters.
For example:
template <class X, class Y> struct S;
#define Macro(arg) S arg;
The extra ( ) workaround used in C cannot be used here:
Macro((<int, int>));
This is important for X-macros for example.
I propose to enhance the cpp to be able to ignore escaped commas (with
\), so this can be done:
Macro(<int\, int>);
We already implemented this extension in gcc (patch to be sent on
Monday) which is working.
What we did is: comma escaping occurs at the top level, but not inside ( ).
For example
SomeMacro(f(a\,b))
does no escape the comma and thus has current behavior.
Feedback?
Thanks,
Daniel.