nana icon indicating copy to clipboard operation
nana copied to clipboard

Compiler error when using boost filesystem

Open Xeverous opened this issue 5 years ago • 11 comments

problem 1:

G:\Files\C++\lib_download\nana\source\gui\filebox.cpp: In member function 'nana::filebox& nana::filebox::init_path(const path_type&)':
G:\Files\C++\lib_download\nana\source\gui\filebox.cpp:1396:39: error: no matching function for call to 'is_directory(const path_type&, std::error_code&)'
   if (p.empty() || is_directory(p, err))
                                       ^
In file included from C:/mingw64/mingw64/include/boost/filesystem.hpp:17,
                 from G:/Files/C++/lib_download/nana/include/nana/filesystem/filesystem.hpp:57,
                 from G:/Files/C++/lib_download/nana/include/nana/paint/graphics.hpp:20,
                 from G:/Files/C++/lib_download/nana/include/nana/gui/effects.hpp:15,
                 from G:/Files/C++/lib_download/nana/include/nana/gui/programming_interface.hpp:16,
                 from G:/Files/C++/lib_download/nana/include/nana/gui/wvl.hpp:18,
                 from G:/Files/C++/lib_download/nana/include/nana/gui.hpp:1,
                 from G:\Files\C++\lib_download\nana\source\gui\filebox.cpp:15:
C:/mingw64/mingw64/include/boost/filesystem/operations.hpp:325:15: note: candidate: 'bool boost::filesystem::is_directory(boost::filesystem::file_status)'
   inline bool is_directory(file_status f) BOOST_NOEXCEPT
               ^~~~~~~~~~~~
C:/mingw64/mingw64/include/boost/filesystem/operations.hpp:325:15: note:   candidate expects 1 argument, 2 provided
C:/mingw64/mingw64/include/boost/filesystem/operations.hpp:453:8: note: candidate: 'bool boost::filesystem::is_directory(const boost::filesystem::path&)'
   bool is_directory(const path& p)     {return is_directory(detail::status(p));}
        ^~~~~~~~~~~~
C:/mingw64/mingw64/include/boost/filesystem/operations.hpp:453:8: note:   candidate expects 1 argument, 2 provided
C:/mingw64/mingw64/include/boost/filesystem/operations.hpp:455:8: note: candidate: 'bool boost::filesystem::is_directory(const boost::filesystem::path&, boost::system::error_code&)'
   bool is_directory(const path& p, system::error_code& ec)
        ^~~~~~~~~~~~
C:/mingw64/mingw64/include/boost/filesystem/operations.hpp:455:8: note:   no known conversion for argument 2 from 'std::error_code' to 'boost::system::error_code&'

Caused by this:

https://github.com/cnjinhao/nana/blob/ffa170b5f560dbf899030bdeb0e539aa95b03649/source/gui/filebox.cpp#L1393-L1400

If the project is compiled with std filesystem, is_directory() gets std::error_code and std::filesystem::path but when the project is compiled with Boost filesystem, the functions gets std::error_code and boost::filesystem::path which does not match any overload. Pehaps nana needs also error_type alias.


problem 2:

G:\Files\C++\lib_download\nana\source\gui\filebox.cpp: In member function 'std::vector<boost::filesystem::path> nana::filebox::show() const':
G:\Files\C++\lib_download\nana\source\gui\filebox.cpp:1487:38: error: no matching function for call to 'to_wstring(nana::filebox::path_type&)'
   auto wpath = to_wstring(impl_->path);
                                      ^
In file included from G:/Files/C++/lib_download/nana/include/nana/basic_types.hpp:16,
                 from G:/Files/C++/lib_download/nana/include/nana/paint/graphics.hpp:18,
                 from G:/Files/C++/lib_download/nana/include/nana/gui/effects.hpp:15,
                 from G:/Files/C++/lib_download/nana/include/nana/gui/programming_interface.hpp:16,
                 from G:/Files/C++/lib_download/nana/include/nana/gui/wvl.hpp:18,
                 from G:/Files/C++/lib_download/nana/include/nana/gui.hpp:1,
                 from G:\Files\C++\lib_download\nana\source\gui\filebox.cpp:15:
G:/Files/C++/lib_download/nana/include/nana/deploy.hpp:71:15: note: candidate: 'std::__cxx11::wstring nana::to_wstring(std::string_view)'
  std::wstring to_wstring(std::string_view utf8_str);
               ^~~~~~~~~~
G:/Files/C++/lib_download/nana/include/nana/deploy.hpp:71:15: note:   no known conversion for argument 1 from 'nana::filebox::path_type' {aka 'boost::filesystem::path'} to 'std::string_view' {aka 'std::basic_string_view<char>'}
G:/Files/C++/lib_download/nana/include/nana/deploy.hpp:77:22: note: candidate: 'const wstring& nana::to_wstring(const wstring&)'
  const std::wstring& to_wstring(const std::wstring& wstr);
                      ^~~~~~~~~~
G:/Files/C++/lib_download/nana/include/nana/deploy.hpp:77:22: note:   no known conversion for argument 1 from 'nana::filebox::path_type' {aka 'boost::filesystem::path'} to 'const wstring&' {aka 'const std::__cxx11::basic_string<wchar_t>&'}
G:/Files/C++/lib_download/nana/include/nana/deploy.hpp:78:17: note: candidate: 'std::__cxx11::wstring&& nana::to_wstring(std::__cxx11::wstring&&)'
  std::wstring&& to_wstring(std::wstring&& wstr);
                 ^~~~~~~~~~
G:/Files/C++/lib_download/nana/include/nana/deploy.hpp:78:17: note:   no known conversion for argument 1 from 'nana::filebox::path_type' {aka 'boost::filesystem::path'} to 'std::__cxx11::wstring&&' {aka 'std::__cxx11::basic_string<wchar_t>&&'}
G:\Files\C++\lib_download\nana\source\gui\filebox.cpp:1524:30: error: 'using path_type = class boost::filesystem::path' {aka 'class boost::filesystem::path'} has no member named 'u8string'; did you mean 'string'?
    impl_->path = parent_path.u8string();
                              ^~~~~~~~
                              string

Some convertions from/to boost filesystem types are missing and/or API wrongly assumes the existence of u8string() method.


https://github.com/cnjinhao/nana/blob/ffa170b5f560dbf899030bdeb0e539aa95b03649/include/nana/filesystem/filesystem.hpp#L60-L115

It is undefined behaviour to inject any names into std namespace other than explicitly allowed template specializations. This code can go in conflict with implementation details of the standard library (eg affect and create mismatched templates/overloads).

If Nana needs to abstract it's filesystem library, aliases and/or helper functions should be made purely in the nana (or child) namespace(s).

Xeverous avatar May 13 '19 20:05 Xeverous

I have found multiple definitions of path_type accross the repository:

$ grep -rn "using path_type" include/ source/
include/nana/gui/filebox.hpp:31:                using path_type = std::filesystem::path;
include/nana/gui/filebox.hpp:104:               using path_type = std::filesystem::path;
include/nana/gui/widgets/skeletons/textbase.hpp:43:             using path_type = std::filesystem::path;
include/nana/gui/widgets/skeletons/text_editor.hpp:69:                  using path_type = std::filesystem::path;
include/nana/gui/widgets/textbox.hpp:112:               using path_type = std::filesystem::path;
include/nana/paint/graphics.hpp:36:                     using path_type = ::std::filesystem::path;
source/detail/platform_abstraction.cpp:161:             using path_type = std::filesystem::path;
source/detail/platform_abstraction.hpp:31:              using path_type = ::std::filesystem::path;
source/paint/truetype.hpp:50:                   using path_type = ::std::filesystem::path;

All of them assume standard library filesystem, which drives me to the question if Boost filesystem support is maintained at all? Weren't these supposed to be implementation-independent aliases? Or is Boost filesystem support a thing of the past and should be removed to avoid confusion?

Xeverous avatar May 13 '19 20:05 Xeverous

what compiler are you using? use a cumpliant modern c++ compiler and you will have std::filesystem and you will need no workaround.

qPCR4vir avatar May 13 '19 22:05 qPCR4vir

If the project is compiled with std filesystem, is_directory() gets std::error_code and std::filesystem::path but when the project is compiled with Boost filesystem, the functions gets std::error_code and boost::filesystem::path which does not match any overload. Pehaps nana needs also error_type alias.

Not that simple, std::error_code is there already, no alias posible. Introduce some convertions operator? or an overload for boost- is_directory() that get std::error_code ... hmm. Or just:

 filebox& filebox::init_path(const path_type& p) 
 { 
 	try{
 	if (p.empty() || is_directory(p, err)) 
 		impl_->path = p; 
 	}cath(...){} 
 	return *this; 
 } 

or just throw:

 filebox& filebox::init_path(const path_type& p) 
 { 
 	if (p.empty() || is_directory(p, err)) 
 		impl_->path = p; 
 	return *this; 
 } 

qPCR4vir avatar May 13 '19 23:05 qPCR4vir

Yes, boost::filesystem is just a workaround for your compiler not providing std::filesystem. Unfortunatelly boost dont full implement the last std::filesystem. One need workarounds to make the workaround work. One can use nana::filesystem

It is undefined behaviour to inject any names into std namespace other than explicitly allowed template specializations

nothing to do with this situation because we ARE IMPLEMENTING the standard, so we need to use std::

If Nana needs to abstract it's filesystem library,

noooo, nana dont need to abstract the filesystem library, it need just std::filesystem

Or is Boost filesystem support a thing of the past and should be removed to avoid confusion?

of course! Who need Boost filesystem? ... well, if you dont have std:: .... use boost and adapt it

qPCR4vir avatar May 13 '19 23:05 qPCR4vir

@Xeverous I couldn't look into the problem you experienced in more detail, but this header-only single-file std::filesystem compatible helper library worked well for me in another case. Maybe you could drop it in?

dnso86 avatar May 14 '19 06:05 dnso86

what compiler are you using?

GCC 8.3.1 with MCF thread model on Windows 10.

Not that simple, std::error_code is there already, no alias posible.

I don't understand what you mean.

Yes, boost::filesystem is just a workaround for your compiler not providing std::filesystem. Unfortunatelly boost dont full implement the last std::filesystem.

I don't undersand this either.

Do you support Boost filesystem or not? The current implementation does not compile when I run CMake with NANA_CMAKE_BOOST_FILESYSTEM_FORCE=ON. Also, judging by https://github.com/cnjinhao/nana/pull/281 and build/cmake/select_filesystem.cmake you have maintained support for it. I have Boost 1.69 and it doesn't compile.

https://github.com/cnjinhao/nana/blob/ffa170b5f560dbf899030bdeb0e539aa95b03649/build/cmake/select_filesystem.cmake#L7-L11

nothing to do with this situation because we ARE IMPLEMENTING the standard, so we need to use std::

This is not a good approach. You should never "implement the standard" this way and then expect std:: to work. Boost filesystem is not an implementation of std filesystem (does not try to have exactly the same interface). It's only a library with very similar API, based on which std filesystem was designed.

My compiler already has standard filesystem (which can conflict with it), I just wanted to use the boost one because of my dependencies. If you want to support multiple filesystem libraries, you should not inject names into std but provide aliases like nana::filesystem::path_type that will be either boost::filesystem::path, std::filesystem::path or your own implementation or helper functions that will work with any implementation.

of course! Who need Boost filesystem? ... well, if you dont have std:: .... use boost and adapt it

If by "adapt" you mean making a PR I can do it, but need some clearance first. The only proper way to support multiple filesystem libraries is through helper functions and aliases in your own (nana) namespace.

Xeverous avatar May 14 '19 11:05 Xeverous

What distro of gcc is that? Until now I have no gcc running filesystem in windows (only MSys64-MinGW-gcc8.3 which have other problems - how to solve the dll problem?). If your std::filesystem works, use it in nana, and Boost as you like but only not in nana. Nana support only std::filesystem, and (ab)use other lib only to implement it. When every major compiler will have proper c++17 any mention of Boost will be deleted from nana.... until we will need it again.

qPCR4vir avatar May 14 '19 12:05 qPCR4vir

Nana support only std::filesystem, and (ab)use other lib only to implement it. When every major compiler will have proper c++17 any mention of Boost will be deleted

Ok, this clears a lot. So you basically use Boost only to workaround non-conformant compilers. The CMake configuration description is misleading.

What distro of gcc is that?

The one build by LH_Mouse, at the bottom of this page. It has more efficient C++-compliant std::thread implementation than compilers using pthread and the compiler itself comes with huge set of prebuild libraries (Boost, zlib, OpenSSL, some GNU libs, Python 2, Python 3, lzma, ncurses, unicode and more) that are automatically detected by CMake and by the compiler itself.

I'm not sure if the std filesystem implementation in my compiler is complete, but nana successfully builds with it (without forced boost).

Xeverous avatar May 14 '19 12:05 Xeverous

Thanks! I used the lastest option from here: https://gcc-mcf.lhmouse.com/ It set: CMAKE_CXX_COMPILER_VERSION = 9.1.1 !!! I changed the build/cmake/compilers.cmake to add static c++ runtime linking but still need to copy mcfgthread-12.dll with the .exe files. See #437 How to fix that? I want all static linked, and move around just my .exe file

qPCR4vir avatar May 15 '19 11:05 qPCR4vir