C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [DRAFT PAPER] Allowing the establishment of namespace scopes in an export-declaration

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Thu, 8 Sep 2022 10:16:00 -0400
On Thu, Sep 8, 2022 at 6:01 AM Zopolis0 via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> > This is a claim made without any evidence that such a thing (using
> > namespaces "without wrapping files in namespace blocks") is even
> >*desireable* let alone something worthy of a language change.
>
> I'm not sure how to give "evidence" that something is desirable.

There are plenty of ways.

For example, you can show some example code of what you have to do
now, then show example code of what your language feature would allow.
You can then, in the text below, highlight what you consider to be
deficiencies in the former which the latter resolves. And most
importantly, you can highlight *why* you consider them to be
deficient, what features of the status quo cause certain problems and
what makes those things problems.

The committee didn't add concepts or structured bindings or lambdas to
the language because they had some personal dislike for the current
ways to achieve things. They added them because the current ways to do
them were very complicated, easy to get wrong, confusing to look at,
and/or otherwise problematic. And they could substantiate all of those
positions by showing what code looked like before and after the change
and making arguments based on them.

For example:

```
auto some_tuple = func();
std::get<2> (some_tuple).stuff;
```

to

```
auto [name0, name1, name2] = func();
name2.stuff;
```

Now, the difference seems clear, but there are particulars that can be
highlighted. The first one has a lot of syntactic noise (`get<2>`,
extra parens, etc) that doesn't really mean much for the programmer.
It has the number `2`, the exact meaning of which is unclear. Yes, it
means to get the 3rd member of the tuple, but what that member
actually represents is unclear.

By contrast, the second one has little noise, and `name2` can be
descriptive of the meaning of the object rather than a bare number.

These are arguments that one can read and agree with or disagree with.
They're not purely personal preferences; they highlight specific flaws
in the original.

At the end of the day, simply saying that the status quo is bad is
unhelpful. Words like "easy" or "hard", "clear" or "simple", etc are
way too subjective. Unless the difference between the two pieces of
code is obvious, you need something more than personal preference to
justify why your suggestion is an improvement.

> Feedback on the wording and formatting of the paper. Is that so hard?

Well, the *content* of the wording is sufficiently lacking that the
wording and formatting is largely irrelevant. It's like asking someone
to comment on the quality of the concrete in a pile of rubble.

However, if you want commentary on the particulars of the standard
wording, it's rather like the motivation section: thin and threadbare,
relying on a lot of "you know what I mean" rather than spelling things
out.

There are two things I would like to highlight in this regard.

The first is the introduction sentence, probably the *most important*
sentence in your proposal:

> This paper proposes to allow the establishment of namespace scopes in an export-declaration and define a syntax for doing so.

Um... what does that *mean*?

I know what that means only because we've had interactions on this
mailing list where you explain what you're trying to do. But if I had
no idea what you're trying to do, I would have no idea what that
entails.

We already have a syntax wherein an `export-declaration` can
"establish" a "namespace scope":

```
export namespace my_namespace
{
}
```

That is an `export-declaration` and it establishes a namespace scope.
All names declared within that scope will be exported.

My understand of what you mean for your feature to do is to shove
every subsequent declaration into the scope of that namespace without
putting the code in the scope of the namespace with curly braces.

But that's not what your sentence describes. In standard-speak, I
believe that what you want to do is to create a declarative region
from that declaration to the end of the file into which all declared
names are members of that namespace.

Even if that's the intent, the introduction section isn't the place to
say it in standard-speak. The introduction is where you describe what
it looks like in C++ layman's terms, not in standard-speak. Your
feature seems to be about making names a member of a namespace without
actually putting them in a namespace declaration. So your introduction
should probably bring that up, since that's the point of the feature.

For the second, consider this key sentence:

> An export-declaration containing a module-name and a namespace-name establishes a named module according to the module-name and establishes and exports a namespace-scope according to the namespace-name.

It is very unclear what this does, and unclear if an
`export-declaration` is even the right tool to use to do it.

What does it mean to "establish a named module"? The word "establish"
tends to be used around scopes, but modules aren't scoped. Do you mean
that such an `export-declaration` means that the translation unit is a
module unit in the module identified by `module-name`?

If so, that's the job of a `module-declaration`, not an
`export-declaration`. It is *very important* in C++ modules that the
`module-declaration` comes early in the file. The point being that
tools can easily tell if a file is a module unit by scanning it and
seeing if you encounter any actual C++ before finding a
`module-declaration` or a `global-module-fragment` section.

This means that by the time you get to your `export-declaration`,
there must have already been a `module-declaration`, which specified
the `module-name`. So what happens if the current module unit's
`module-name` is different from the one specified by this special
`export-declaration`:

```
module my_name;

export different_name some_namespace;
```

So let's assume you meant that this is part of a `module-declaration`
instead. But every `module-declaration` of the form `export module
module-name` is an *interface* unit, not an implementation unit. So
you can't even use your feature in module implementation units.

Also, it's not clear what it means to "export a namespace-scope".
Currently, the standard doesn't export "scopes"; it exports names,
which may be declared *within* a scope. So, what is the scope whose
declarations are being exported? Does this mean that every `namespace
X{}` scope from that point forward will export its declarations as
though it were written as `export namespace X{}`?

Lastly, from your previous thread and the comments here, I gather that
you want to avoid putting declarations into a namespace by using
regular C++ syntax. That is `namespace X {declarations}`. If you mean
for all `declarations` to implicitly and automatically be part of some
namespace, nothing in your wording causes that to happen.
[basic.namespace.scope] establishes what names are inside of a
namespace and what names are not. So if you intend for your feature to
change how that works, it needs to change stuff in there.

Received on 2022-09-08 14:16:33