简体   繁体   中英

C++ CodeBlocks upgrade to C++17 can't use std::filesystem

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:

在此处输入图片说明

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

在此处输入图片说明

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

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). 在此处输入图片说明 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;
    }
}

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM