STL
STL copied to clipboard
`<filesystem>`: compiler error using `directory_iterator`/`recursive_directory_iterator` inside a struct/class with modules
Describe the bug
when recursive_directory_iterator or directory_iterator is used inside a modules export block, the following code will compile; if this same code is then wrapped by a struct/class the code will never compile when the method is called with the following issue(s) of 2 depending on the code setup:
-
missing std::partial_order from
#<compare>, although if this header is included (which should not be required) the following error will happen instead
..\include\type_traits(2118,13): error C2678: binary '&': no operator found which takes a left-hand operand of type '_Bitmask' (or there is no acceptable conversion)
with
[
_Bitmask=__std_fs_file_attr
]
Command-line test case
main.cpp
#include <compare>
import brokenIter;
int main() {
/*
without #include <compare> code will complain about missing std::partial_order from #compare
with #include <compare> the code during build output will generate the given error (which is also reflected as a compile error):
..\include\type_traits(2118,13): error C2678: binary '&': no operator found which takes a left-hand operand of type '_Bitmask' (or there is no acceptable conversion)
with
[
_Bitmask=__std_fs_file_attr
]
*/
//the problem functions defined are the 2 below, a static or non static method both exibits the compile error described above
thing thingO = thing();
thingO.iterDirBroken1();
thing::iterDirBroken2();
//the following function will work though if the previous 2 are not compiled
noStructIter();
return 0;
}
brokenIter.ixx
module;
#include <filesystem>
export module brokenIter;
export{
struct thing {
void iterDirBroken1() {
for (const auto& i : std::filesystem::recursive_directory_iterator(".")) {
}
}
inline static void iterDirBroken2() {
for (const auto& i : std::filesystem::recursive_directory_iterator(".")) {
}
}
};
void noStructIter(){
for (const auto& i : std::filesystem::recursive_directory_iterator(".")) {
}
}
}
compile command:
cl /EHsc /W4 /WX /std:c++latest .\brokenIter.ixx .\main.cpp
Expected behavior
code does not compile with or without #<compare> due to struct/class method using recursive_directory_iterator or directory_iterator
(if you remove #<compare> there will be a different compile error which still is not supposed to be there)
STL version
Microsoft Visual Studio Community 2022
Version 17.6.0 Preview 4.0 although the behavior happened on 17.5.4, and 17.6 Preview 2.0, and Preview 3.0
Additional context
exact same (minimum reproducible code) I used to get a compile error: https://github.com/16-Bit-Dog/BrokenFileSystemOn17.6
same compiler issue but elaborated upon in relation to #3330
FYI @cdacamar this looks like a compiler bug.
I observe that this works if broken_iter.ixx says import std;.
The following imports should not be required though, no?
This is still present in 17.8. I noticed that by replacing #include <compare> with #include <filesystem> in your example, there are no errors. Whatever that means.
In my case, the problem occurs when using std::filesystem:exists() in a member function in a class in module. Indeed, if I replace the content of the functions of your example with std::filesystem::exists("."); I get the same error. The workaround mentioned above works in this minimal example, but not in my real code.
Using #include <filesystem> at the module import location (in the global module fragment, if necessary) definitely fixes the issue for me.
Does this still repro with VS 2022 17.10 or later? I improved the STL so that include-before-import (but not the other order) works, with #4154 in VS 2022 17.10.
I can reproduce this problem with VS 2022 17.10.3