Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Macros #1448

Eljay-pga started this conversation in Suggestions
Macros #1448
May 4, 2026 · 1 comments · 6 replies
Discussion options

How does C++ Syntax 2 obviate macros and/or the need for macros?

C++ macros make me cry.

You must be logged in to vote

Replies: 1 comment 6 replies

Comment options

Cpp2 doesn't support writing macros. It does allow using normal C++ (aka Cpp1) macros, but I find I use them fairly rarely.

I haven't eliminated all the reasons to write text macros, but most have been replaced by two main things:

  • that C++20/23/26 already have been greatly increasing what constexpr/consteval functions can do; and
  • reflection (available in cppfront, and just now starting to become available in standard C++ in C++26) including using reflection to author classes (Cpp2 metaclasses which also should come into standard C++ post-C++26 because most of what it needs is now already in C++26).

(Fun fact: Both C++20 consteval and C++26 reflection came from the Cpp2 work before it got the name Cpp2 and before there was cppfront, via Andrew Sutton's team's Lock3 reflection implementation work in a Clang fork. consteval came directly from that work when Andrew noticed the need for it and proposed the keyword and semantics for the standard. C++26 reflection also came from it when Dan Katz took Andrew's team's Clang implementation and then did a huge amount of further proposal-writing and implementation work to carry reflection the rest of the way across the finish line into C++26. Thanks again, Andrew's team and Dan and Daveed and Matus and everyone who worked on reflection!)

You must be logged in to vote
6 replies
Comment options

@Eljay-pga Why is that better than this?

GLOBAL_FOO: i32 = 0xBAD;
main: () = {
 LOCAL_FOO: i32 = 0x600D;
 std::cout << LOCAL_FOO << "\n"; // output: 24589
 std::cout << GLOBAL_FOO << "\n"; // output: 2989
}

(Which would also put the $ to good use. About time to give $ something to do!)

Cpp2 already uses $ for captures.
https://hsutter.github.io/cppfront/cpp2/expressions/#captures-including-interpolations

Comment options

@gregmarr • Do syntax 1 macros get expanded in the context of syntax 2?

I would prefer that syntax 1 macros would require explicit expansion in the context of syntax 2. Because the preprocessor is The DevilTM.

(My bad. I didn't know that $ already has a "paste the value of" capture/interpolation use case. I'm just learning about Syntax 2 now — and so far I'm loving it. Reminds me of Werther and Conway's "A Modest Proposal: C++ Resyntaxed" from 1996.)

Comment options

I agree with removing the need to author macros. Cpp2 doesn't author macros, so I view macros as a compatibility question with Cpp1 and C including their ecosystem and libraries. And C macros are designed to be transparently "overloadable" with objects and functions... consider:

If we did require explicit expansion syntax when using macros, that would break compatibility with using libraries (including the C standard library included as C, when using #include <stdlib.h> rather than #include <cstdlib>) that do not specify whether a function is really a function or is a macro. The C standard library goes the other way: It says that writing abs(x) (for example) could invoke either a macro or a function, and if you want the function you have to explicitly do that via calling it as (abs)(x) or taking its address as &abs. C++ makes this less of an issue with the C stdlib when using the <cstdlib> style headers (e.g., abs must be only a function, and only a few things like offsetof are always a macro), but that doesn't stop third-party C (or C++) libraries from using this idiom. There are two cases:

  • If the library always uses a macro for a given function f, Cpp2 calling code would need to know that and call it as ${f} (and then depend on that implementation detail, and be brittle to the library changing it to a function later).
  • If the library sometimes uses a macro for a given function f (say in debug or instrumented builds) and sometimes makes it a real function, then how could we call it at all from Cpp2 code if those require two different syntaxes?

Here I'm talking about function-like macros, but there are similar issues with object-like macros (e.g., for OBJ.member, requiring a different syntax depending on knowing whether OBJ is a macro or an object name has similar problems).

Also, requiring explicit expansion (as a strawman for discussion say using your syntax) would mean that Cpp2 code would require users to write something like @{offsetof} everywhere.

Finally, as a practical matter, I'm not sure whether cppfront could know it's a macro. It would be easy to allow an explicit expansion syntax (it would just be ignored after parsing, though that's of questionable usefulness). What would be hard would be to require it, since I don't know of an easy way for cppfront to know whether something is a macro, without some heroic effort of generating an #ifdef for every use of an object or function.

Comment options

Thank you, that makes sense. I appreciate taking the time to answer my inquiry. (Drat. But it is what it is.)

Comment options

[Edit to correct some comments. A major downside of a macro is, of course, that it hijacks the name for all other code.]

No worries, thanks for the inquiry. I think it's a useful observation that C macros provide an "overloadable" single syntax for objects/object-like-macros and functions/function-like-macros is an issue for generic code. Conversely, C++ doesn't provide a single syntax for calling non-member functions and member functions, and that's is a barrier to generic code -- and "generic" doesn't mean only templates:

  • it's a barrier to template code which has to pick whether to call a member vs non-member (we're still dealing with that via partial workarounds like std::begin as a non-member);
  • but it's also a barrier to ordinary 'generic' code in that a function-like macro is an alternative for non-member functions but not member functions, because function-like macros can't easily use a easy non-member call syntax (incidentally this is one of the major reasons for lambdas in the language, because lambda libraries like Boost.Lambda were never able to deal well with member functions).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /