cnjinhao / nana

a modern C++ GUI library
https://nana.acemind.cn
Boost Software License 1.0
2.34k stars 335 forks source link

Compiler error when using boost filesystem #434

Open Xeverous opened 5 years ago

Xeverous commented 5 years ago

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 commented 5 years ago

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?

qPCR4vir commented 5 years ago

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

qPCR4vir commented 5 years ago

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 commented 5 years ago

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

dnso86 commented 5 years ago

@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?

Xeverous commented 5 years ago

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.

qPCR4vir commented 5 years ago

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.

Xeverous commented 5 years ago

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).

qPCR4vir commented 5 years ago

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

thomasgpeters commented 3 months ago

getting this same error when compiling on macos 14.6 Beta (Sonoma) as well as earlier versions of macos. Wt will make on my ubuntu 24.04 environment so this issue is constrained to macos systems at this time. I am a bit wet behind the ears, but do understand the dialog you guys had earlier in 2019. Humph... it's a long time ago.

Apple clang version 15.0.0 (clang-1500.3.9.4) Target: x86_64-apple-darwin23.6.0 Thread model: posix

GNU Make 3.81 cmake version 3.30.1

cmake output : Found Boost 1.85.0 at /usr/local/lib/cmake/Boost-1.85.0

qPCR4vir commented 1 month ago

@thomasgpeters sorry... Are you using develop-1.8? The Master branch is very old.