g ++ критическое изменение в std :: filesystem :: last_write_time - PullRequest
3 голосов
/ 21 июня 2019

С недавним обновлением ОС я заметил, что небольшая часть моего кода перестала компилироваться - похоже, причина заключается в переключении с g++-8 на g++-9.

Этот код правильно компилируется на g++ 8.3.0 (подтвердите это, используя gcc:8.3 изображение из Dockerhub)

#include <filesystem>
#include <chrono>

int main() {
    namespace fs = std::filesystem;
    using namespace std::chrono_literals;
    std::filesystem::last_write_time("test", std::chrono::system_clock::now() - 5min);
}

При g++ 9.1.0 происходит сбой:

test.cpp: In function 'int main()':
test.cpp:8:69: error: no matching function for call to 'last_write_time(const char [5], std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000000> > >)'
    8 |  fs::last_write_time("test", std::chrono::system_clock::now() - 5min);
      |                                                                     ^
In file included from /usr/local/include/c++/9.1.0/filesystem:39,
                 from test.cpp:1:
/usr/local/include/c++/9.1.0/bits/fs_ops.h:243:19: note: candidate: 'std::filesystem::file_time_type std::filesystem::last_write_time(const std::filesystem::__cxx11::path&)'
  243 |   file_time_type  last_write_time(const path& __p);
      |                   ^~~~~~~~~~~~~~~
/usr/local/include/c++/9.1.0/bits/fs_ops.h:243:19: note:   candidate expects 1 argument, 2 provided
/usr/local/include/c++/9.1.0/bits/fs_ops.h:244:19: note: candidate: 'std::filesystem::file_time_type std::filesystem::last_write_time(const std::filesystem::__cxx11::path&, std::error_code&)'
  244 |   file_time_type  last_write_time(const path& __p, error_code& __ec) noexcept;
      |                   ^~~~~~~~~~~~~~~
In file included from /usr/local/include/c++/9.1.0/filesystem:36,
                 from test.cpp:1:
/usr/local/include/c++/9.1.0/bits/fs_fwd.h:362:47: note:   no known conversion for argument 2 from 'std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000000> > >' to 'std::error_code&'
  362 |   file_time_type last_write_time(const path&, error_code&) noexcept;
      |                                               ^~~~~~~~~~~
In file included from /usr/local/include/c++/9.1.0/filesystem:39,
                 from test.cpp:1:
/usr/local/include/c++/9.1.0/bits/fs_ops.h:245:8: note: candidate: 'void std::filesystem::last_write_time(const std::filesystem::__cxx11::path&, std::filesystem::file_time_type)'
  245 |   void last_write_time(const path& __p, file_time_type __new_time);
      |        ^~~~~~~~~~~~~~~
/usr/local/include/c++/9.1.0/bits/fs_ops.h:245:56: note:   no known conversion for argument 2 from 'time_point<std::chrono::_V2::system_clock,[...]>' to 'time_point<std::filesystem::__file_clock,[...]>'
  245 |   void last_write_time(const path& __p, file_time_type __new_time);
      |                                         ~~~~~~~~~~~~~~~^~~~~~~~~~
/usr/local/include/c++/9.1.0/bits/fs_ops.h:246:8: note: candidate: 'void std::filesystem::last_write_time(const std::filesystem::__cxx11::path&, std::filesystem::file_time_type, std::error_code&)'
  246 |   void last_write_time(const path& __p, file_time_type __new_time,
      |        ^~~~~~~~~~~~~~~
/usr/local/include/c++/9.1.0/bits/fs_ops.h:246:8: note:   candidate expects 3 arguments, 2 provided

shell returned 1

Press ENTER or type command to continue

Команда компиляции: g++ -std=c++17 test.cpp -lstdc++-fs (даже если связывать stdc++-fs не нужно, поскольку g++9)

Мой вопрос - в чем идиоматическое использование этой функции, как я задумал? А именно, изменение времени последней записи файла на пять минут назад.

Я понимаю, что использовал это каким-то идиоматическим образом, если было внесено критическое изменение.

Ответы [ 2 ]

7 голосов
/ 21 июня 2019

Как указал @LightnessRacesinOrbit в своем ответе, std::filesystem::file_time_type, который принимает last_write_time, использует неопределенный тип time_point.Это означает, что для этого вполне законно прервать переход от одного компилятора к другому или даже к версиям одного и того же компилятора.

Что вы можете сделать, так это получить часы, используемые реализацией, и использовать их самостоятельно.std::chrono::time_point был построен, чтобы принять тип часов, который создает его, как параметр шаблона, и он отображает открытый тип clock, который представляет это.Таким образом, чтобы получить часы и позвонить на них now, вы можете использовать

std::filesystem::last_write_time("test", std::filesystem::file_time_type::clock::now() - 5min);
//                                       ^ give me whatever clock you use and call now on it
3 голосов
/ 21 июня 2019

Это касается примера cppreference.com .

Вы дали std::chrono::time_point<std::chrono::system_clock> до std::file_time_type никогда не было переносимым;это случилось с вашей предыдущей цепочкой инструментов.Это была не ваша вина: вы неизбежно полагались на детали реализации.

C ++ 20 представил переносную альтернативу, поэтому вы должны сделать:

std::filesystem::last_write_time("test", std::chrono::file_clock::now() - 5min);
//                                                    ^^^^^^^^^^

… т.е. использоватьfile_clock вместо того, чтобы надеяться, что альтернатива может быть преобразована в любые часы, определенные реализацией, используемые вашей цепочкой инструментов.

Поддерживается ли это в GCC 9, я не могу точно сказать, хотя этоне похоже на это .Если есть обходной путь, я не знаю ни одного (именно поэтому было сделано изменение в C ++ 20.)

Эта проблема также влияет на других людей на других цепочках инструментов .

...