Why does exporting a type alias such as std::vector<std::string> in a module allow use of both std::vector and std::string in some internal partition?
Asked Answered
M

2

9

I am currently using Visual Studio 2022 Update 17.1.6, and I found something interesting with exporting type alias. For reasons I don't understand, when I export a type alias for some data type such as std::vector<std::string> in a module interface file, I can use both std::vector<> and std::string in the file that imported it. For example:

modInterface.ixx

export module words;
import <iostream>
import <vector>;
import <string>;
...
export using Words = std::vector<std::string>;
...

In an internal partition:

modInternalPartition.cpp

module words:wordsIP;
import words;

//This compiles as expected
Words wordStorage;

//Why does my compiler sees below as correct, and compiles it without error?
std::vector<int> numStorage = { 1, 2, 3, 4 };

//Why does my compiler also sees below as correct, and compiles it without error?
std::string text = "This dish is tasty";

//This would produce an error, which is expected since I did not export import <iostream> in modInterface.ixx
std::cout << text;
...

My first thought was that since Words is a type alias, exporting it would mean exporting std::vector<> and std::string, but since std::vector<> is a template, why is it not the case that only the instantiation of it (std::vector<std::string>) is exported?

Mephistopheles answered 2/5, 2022 at 2:5 Comment(6)
I strongly suspect the answer is "templates are all or nothing", but not knowing the new C++20 module system very well, I don't know enough to say whether it's supposed to be less leaky than that.Undercoat
It seems hard to export std::vector<T> without also exporting T, because otherwise how are a bunch of member functions supposed to work? But I don't know the actual standard language to that effect, or whether or not you're supposed to get the whole template. Interesting question.Quirites
@NathanPierson Yeah, I understand that T would need to be exported given the nature of the type alias after some own thinking. I'm wondering why C++20 (or just Visual C++20) decided that I can just use all possible instantiations of std::vector<T> rather than the specific instance I used, since even if I just have that specific instance, I would likely still be able to access all of std::vector<T>'s member functions.Mephistopheles
what are import and export module? new c++ keywords?Pembrook
@BЈовић Yes. import is analogous to #include, while export module means that the module file can be imported to other files, even those that are not in the same module. Bit of a simplification though.Mephistopheles
@AR ok, thanks. i thought those are windows extensionsPembrook
L
3

Here's a funny thing about modules: export declarations only matter for code outside of a module.

If you import a module unit that is part of the same module as yourself, you have access to all of the declarations in that module unit. This allows you to have "private" declarations which are not exported to the module's interface, but are still accessible to other code within the module. This includes module imports:

Additionally, when a module-import-declaration in a module unit of some module M imports another module unit U of M, it also imports all translation units imported by non-exported module-import-declarations in the module unit purview of U.

Header units are not special in this regard. You imported those header units, so they are imported by your primary module interface. Therefore, any module implementations for that module that import your primary module interface will see them.

Ljubljana answered 2/5, 2022 at 3:19 Comment(2)
I've tested by removing the export from the Words type alias, and when I tried to compile again after commenting out Words wordStorage; from modInternalPartition.cpp, the VS2022 compiler throws up an error of 'vector': is not a member of 'std'. If I understand you correctly, I should have access to 'vector' in modInternalPartition.cpp since I imported the module in modInterface.ixx, and the internal partition is part of the module words. But VS2022 keeps throwing up that error, so I still don't really understand. Sorry about that.Mephistopheles
EDIT: I think between you and @DavisHerring, I got my answer. Thanks.Mephistopheles
D
4

When one part of a module imports another, all declarations not affected by internal linkage are available as if they were exported. That applies even to import declarations (and to the implicit import of a module by its non-partition implementation units), so the import <vector>; etc. are available in the words:wordsIP partition. The export has nothing to do with it at all.

Destitution answered 2/5, 2022 at 3:18 Comment(2)
I've tested by removing the export from the Words type alias, and when I tried to compile again after commenting out Words wordStorage; from modInternalPartition.cpp, the VS2022 compiler throws up an error of 'vector': is not a member of 'std'.Mephistopheles
@AR: That’s a compiler bug, then.Destitution
L
3

Here's a funny thing about modules: export declarations only matter for code outside of a module.

If you import a module unit that is part of the same module as yourself, you have access to all of the declarations in that module unit. This allows you to have "private" declarations which are not exported to the module's interface, but are still accessible to other code within the module. This includes module imports:

Additionally, when a module-import-declaration in a module unit of some module M imports another module unit U of M, it also imports all translation units imported by non-exported module-import-declarations in the module unit purview of U.

Header units are not special in this regard. You imported those header units, so they are imported by your primary module interface. Therefore, any module implementations for that module that import your primary module interface will see them.

Ljubljana answered 2/5, 2022 at 3:19 Comment(2)
I've tested by removing the export from the Words type alias, and when I tried to compile again after commenting out Words wordStorage; from modInternalPartition.cpp, the VS2022 compiler throws up an error of 'vector': is not a member of 'std'. If I understand you correctly, I should have access to 'vector' in modInternalPartition.cpp since I imported the module in modInterface.ixx, and the internal partition is part of the module words. But VS2022 keeps throwing up that error, so I still don't really understand. Sorry about that.Mephistopheles
EDIT: I think between you and @DavisHerring, I got my answer. Thanks.Mephistopheles

© 2022 - 2024 — McMap. All rights reserved.