Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`using` inside a namespace in C++ module is not limited to the namespace

Given the following module example

module;

#include "example.h" // `namespace cxx { struct example {}; }`

export module example;

export namespace cxx::containers
{
    using cxx::example;
}

cxx::containers::example becomes accessible from cxx::example as well where I only expected cxx::containers::example to appear.

import example;

int main()
{
    auto v1 = cxx::containers::example();
    auto v2 = cxx::example();
}

What is the reason that cxx::example is visible even though I am only using it inside the namespace cxx::containers::example and that #include directives in the global module; fragment should be localized to their module?

like image 917
Ricky Spanish Avatar asked Dec 09 '25 14:12

Ricky Spanish


1 Answers

The strict answer ("the reason that cxx::example is visible") is that it's an MSVC bug: the declaration of cxx::example isn't exported, so it isn't found by name lookup outside the module in question ([basic.lookup.general]/2.3, except in certain circumstances involving dependent ADL ([basic.lookup.argdep]/4)).

Since C++20 was published, the wording for using-declarations has been significantly revised to clarify the relationship between the original and new declaration. A using-declaration is not a redeclaration of the original entity or typedef (which is why it can be separately exported); instead, name lookup replaces a using-declarator with the declarations to which it refers ([basic.lookup.general]/3). The using-declaration for cxx::containers::example precedes main because it is exported (/2.3); the declaration of cxx::example itself does not, so it isn't found ([basic.lookup.qual.general]/3, [class.member.lookup]/1, and a different part of [basic.lookup.general]/3) except via the aforementioned replacement.

The wording for the only distantly related using-directive has also changed (as a retroactive Defect Report) to generally allow and give meaning to exported using-directives ([basic.lookup.unqual]/1, [namespace.qual]/1, [module.interface]/4). (They could already be exported in header units.) Of course, if you don’t export them you can use them just for convenience within a module without affecting your clients!

like image 186
Davis Herring Avatar answered Dec 11 '25 02:12

Davis Herring



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!