0

I need to be able to list the files in a directory, and so I'm trying to upgrade my C++ version in CodeBlocks to C++ 17 so i can use filesystem. To do this I followed the steps outlined at http://candcplusplus.com/enable-c17-in-code-blocks-mingw-gcc-for-all-version-with-pictures#:~:text=Enabling%20the%20C%2B%2B17,Create%20a%20project.

I didnt have to change much, CodeBlocks 20.03 and MinGW 8.1.0 are already installed. MinGW is already in my path from when I built wxWidgets. The Settings->Compiler...->Toolchain executables tab I didnt have to make any changes to, and appears in CodeBlocks as:

enter image description here

I also checked the box to use C++ 17 in compiler settings like so

enter image description here

I ran the test program on the website with the instructions and got "True!".

However when I change the basic test program to this, to try and use filesystem to read files in a directory, I get an error:

#include <iostream>
#include <filesystem>

using namespace std;

int main()
{
    const int i=90;

    if constexpr (i) //'if constexpr' is part of C++17
    {
        cout << "True!";
    }
    else
    {
        cout<<"False" ;
    }

    std::string path = "../MagicProgCPP/files/debug images/";
    for (const auto & entry : filesystem::directory_iterator(path))
    {
        cout << entry.path() << std::endl;
    }


    cin.get();
    return 0;
}

The program stops building, opens the file fs_path.h and stops on this line:

#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
      if (__p.is_absolute()
      || (__p.has_root_name() && __p.root_name() != root_name()))     <----- ******STOPS HERE
    operator=(__p);
      else
    {
      string_type __pathname;
      if (__p.has_root_directory())
        __pathname = root_name().native();
      else if (has_filename() || (!has_root_directory() && is_absolute()))
        __pathname = _M_pathname + preferred_separator;
      __pathname += __p.relative_path().native(); // XXX is this right?
      _M_pathname.swap(__pathname);
      _M_split_cmpts();
    }
#else
      // Much simpler, as any path with root-name or root-dir is absolute.
      if (__p.is_absolute())
    operator=(__p);
      else
    {
      if (has_filename() || (_M_type == _Type::_Root_name))
        _M_pathname += preferred_separator;
      _M_pathname += __p.native();
      _M_split_cmpts();
    }
#endif
      return *this;
    }

I get this error in the build log:

C:\Program Files\CodeBlocks\MinGW\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\bits\fs_path.h|237|error: no match for 'operator!=' (operand types are 'std::filesystem::__cxx11::path' and 'std::filesystem::__cxx11::path')|

I'm prety confident the path exists as I entered it and there's files in it. The build log message suggests maybe I'm not using C++17? But when I click build, this is the line the program uses to build:

g++.exe -Wall -fexceptions -g -Wall -std=c++17  -c E:\testc17\main.cpp -o obj\Debug\main.o

What am I doing wrong? Thanks

Geoff L
  • 765
  • 5
  • 22
  • I believe it is this compiler bug: [https://sourceforge.net/p/mingw-w64/bugs/737/](https://sourceforge.net/p/mingw-w64/bugs/737/) – drescherjm Sep 08 '20 at 22:11
  • 1
    I expect you have to upgrade mingw to a version more recent than 8.1 – drescherjm Sep 08 '20 at 22:12
  • Ah ok thanks yeah that bug report looks exactly like what I'm experiencing. Thanks for your help – Geoff L Sep 08 '20 at 22:28
  • [Here are instructions to get a mingw install](https://stackoverflow.com/questions/30069830/how-to-install-mingw-w64-and-msys2) that's up to date and has an excellent package manager so you can easily stay up to date. It also has an excellent ecosystem of tools and libraries so you don't have to waste time individually downloading and custom-building likes of SSL, Boost, and cURL (most of the time). Very groovy and time-saving. – user4581301 Sep 08 '20 at 22:35
  • @drescherjm Might as well formalize that as an answer. Hopefully it'll make it easier on the next person who runs into it. – user4581301 Sep 08 '20 at 22:36
  • I have added an answer that summarizes the 3 comments. – drescherjm Sep 09 '20 at 12:13

2 Answers2

1

The bug 78870 was fixed since 2018-07.
You should add to project options -> linker settings -> link libraries the following library: stdc++fs. I tried to compile your code with MinGW gcc 8.1.0 (via CodeBlocks) and everything works well (clearly with another path, since I don't have the same directories as you). enter image description here You could also add a check on the existence of the search directory like this:

namespace fs = std::filesystem;
std::string mypath { "../MyDir" };
if(fs::exists(mypath))
{
    for(const auto & entry : fs::directory_iterator(path))
    {
        cout << entry.path() << std::endl;
    }
}
Sergio
  • 891
  • 9
  • 27
0

It appears that this exact problem is a known bug in mingw 8.1. The bug report is here: https://sourceforge.net/p/mingw-w64/bugs/737/

and has the error in the same location:

operator != is declared and defined in line 550, but referenced in line 237.

The problem is triggered by operator/= in line 233:

    path& operator/=(const path& __p)
    {
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
      if (__p.is_absolute()
      || (__p.has_root_name() && __p.root_name() != root_name()))
    operator=(__p);
      else
    {
      string_type __pathname;
      if (__p.has_root_directory())
        __pathname = root_name().native();
      else if (has_filename() || (!has_root_directory() && is_absolute()))
        __pathname = _M_pathname + preferred_separator;
      __pathname += __p.relative_path().native(); // XXX is this right?
      _M_pathname.swap(__pathname);
      _M_split_cmpts();
    }

The bug report said this was fixed in master meaning you need to install a version of mingw with the fix applied. I believe the best method is to upgrade mingw to a version greater than 8.1

user4581301 commented above in the main question that the following link has instructions on how to get a mingw install: How to install MinGW-w64 and MSYS2?

drescherjm
  • 10,365
  • 5
  • 44
  • 64