C++ Logo

sg7

Advanced search

Re: [SG7] Necessity of the unquote operator %{}

From: David Vandevoorde <daveed_at_[hidden]>
Date: Wed, 24 Mar 2021 11:34:31 -0400
> On Mar 23, 2021, at 6:46 PM, David Rector via SG7 <sg7_at_[hidden]> wrote:
>
> I’ve come around on most of Andrew’s syntax: [::] seems really to be better than $ after trying it out, considering all the parentheses that would be needed in typical usages, etc.
>
> But there remains a complexity from P2237 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2237r0.pdf <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2237r0.pdf>) which I am having trouble understanding. Section 7 contains extensive usage of the "unquote operator" %{}, and discussion of it, particularly in 7.1.7.
>
> Here is the relevant section in its entirety, adjusted to use P2320 syntax (i.e. [::] replaces ||):
> > ### 7.1.7 Unquote
> > The unquote operator allows the use of local variables and expressions involving local variables inside a fragment. For example:
> > ```
> <page31image1074358928.png>
> > consteval meta::info make_fragment(meta::info t) {
> > return <struct {
> > typename [:%{t}:] obj;
> > }>;
> > }
> > ```
> > The function returns a fragment that includes a splice involving the parameter t. Within the fragment, the unquote operator designates a placeholder for a constant expression. Because an unquoted expression is a placeholder, it is type-dependent, meaning that we need to write typename before the declaration. The value for that placeholder is computed during constant expression evaluation as part of the fragment value and is replaced by its corresponding value during injection.
> >
> > The unquote operator can also include more complex expressions:
> > ```
> > consteval meta::info make_fragment(meta::info t) {
> > return <struct {
> > typename [:%{meta::add_pointer(t)}:] ptr;
> > }>;
> > }
> > ```
> > The resulting fragment will inject a pointer to the type reflected by t into the program.
>
> Even with this explanation, I still do not understand the need for %{}. As an lvalue `t` is already a placeholder for a value, and in each call to `make_fragment` it will already be replaced during constant evaluation with a particular rvalue. What work does %{} do beyond that? What am I missing?
>
> More to the point:
> a) Can Andrew & co present an example of an unquote operator usage in which it is plainly necessary, i.e. where the user’s intent is not clear without it?
> b) Might we adjust the syntax to say the unquote operator is not strictly needed wherever the intent of the user is unambiguous without it?

The unquote operator affects lookup . Consider:

...

auto frag = <namespace {
  X* begin(Y) { ... } // (1)
  bool algo(typename[:%{begin(rs)}:] start) { ... }
     // This `begin` is guaranteed never to find (1).
};

 Daveed


Received on 2021-03-24 10:34:36