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: Mon, 12 Sep 2022 13:55:57 -0400
On Mon, Sep 12, 2022 at 3:20 AM Zopolis0 via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> > Your "old.h/cpp" examples don't use namespaces at all. `old` is a
> > class, not a namespace.
>
> A typo. Treat it as if I used namespaces.
>
> > Just your example raises many questions.
> > For example, what namespace is `foo` in?
> It is not in a namespace
> > How do you access them if they're not in the namespace?
> As you would normally.
> > If non-exported names aren't in that namespace, can you define two
> > entities, one exported and one not, with the same name and have that
> > just work because of the implicit namespace business?
> Hmm. In theory, possibly, but that seems messy. I'm going to say no.
>
> > And you never deal with the question of multiple translation units,
> > which is at present a complete non-starter.
> I asked you for help on this, and you asked for examples.
> I gave examples, and now you are asking me the same question that I asked you for help with.
> Regardless, multiple translation units would work the same way as they would previously, and would not care about the namespace declared in the primary module interface unit. The only files that would care are files that import the primary module interface unit, as they would access the exported name via the declared namespace.

Every name in C++ is declared within a specific namespace. That is
what defines what that name is. Two entities that have the same name
in the same namespace may represent the same entity. And the global
namespace is a namespace like any other; it isn't special (though it
does have a special way to refer to it).

However, you can sometimes access an entity through a different
namespace. Inline namespaces allow you to access entities declared in
the inline namespace as if they were declared in the containing
namespace. Similarly, `using` declarations allow you to access names
from a different namespace without explicitly qualifying them as such.

So it seems to me that what you're trying to say works something more
like that. That is, what you're saying is that this:

```
export module something namespace foo;

export void func();
```

Should be equivalent to this:

```
//Implied module file
export module _internal_something;

export void func();

//Actual module file
export module something;
import _internal_something;

namespace foo
{
  export using ::func;
  //More stuff exported by the module `_internal_something`.
}
```

Now, I honestly don't know how `export` works with `using`
declarations like this, but that's not the point. I'm trying to
understand what kind of behavior you want. So my understanding of what
you want is this:

The names are in the global namespace; that is the native namespace in
which they reside. Importing the module blocks you from accessing
those names *though* the global namespace, and also re-exports them
through the specified namespace.

My above equivalent performs these by putting all the actual module
definition in a separate module which is not exported, and then
rebuilding the module interface anew via explicitly exporting each
name in a namespace via using.

The rest of this mail will assume that this is the behavior you want.

This would not be a problem from a basic module build perspective. The
entities in question have module linkage, so they shouldn't conflict
with entities in other modules even if they're all global. And since
the global accessibility of them is blocked, importing two such
modules wouldn't be a problem.

While this feature is implementable, it's still bad for numerous reasons.

You are essentially saying that if a user sees this:

```
export module my_mod:part1;

export void foo();
```

And the user does this:

```
import my_mod;

int main()
{
  foo();
};
```

This may *or may not* be a compile error, depending on something
specified in the primary module interface file. That is, a user cannot
read an interface partition file and actually know how the interface
works.

Do you *really* want something written in a one file to have such a
substantial effect on stuff in a different file? Isn't one of the
points of module units to *prevent* leakage of things like that?

Received on 2022-09-12 17:56:54