Нет оператора + для std::filesystem::path?

Можно добавлять несколько путей подряд с помощью оператора / :

  std::filesystem::path p1{"A"};
  auto p2 = p1 / "B" / "C";

что довольно удобно. Однако concat предлагает только +=:

  std::filesystem::path p1{"A"};
  auto p2 = p1 / "B" / "C" + ".d";   // NOT OK

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

  std::filesystem::path p1{"A"};
  auto p2 = p1 / "B" / "C";
  p2 += ".d";

Я что-то упускаю? Есть ли причина такого несоответствия?


person Touloudou    schedule 27.01.2021    source источник
comment
Неа. Другого пути нет   -  person Raildex    schedule 27.01.2021
comment
@KamilCuk невозможно с const char[N], это было бы auto p2 = p1 / "B" / (std::string("C") + ".d");   -  person PeterT    schedule 27.01.2021
comment
("C" + ".d") добавляет два const char[2]   -  person Caleth    schedule 27.01.2021
comment
@KamilCuk строковый литерал типа A имеет тип const char[N] и будет преобразован в const char* при использовании оператора +, поэтому вы добавляете два указателя с помощью "A"+"B"   -  person PeterT    schedule 27.01.2021
comment
обратите внимание, что на практике "C", скорее всего, также будет std::filesystem::path, поэтому второй вариант не сработает. Первый странный, но должен работать. :)   -  person Touloudou    schedule 27.01.2021
comment
тааак. auto p2 = p1 / "B" / "C" += ".d"; или auto p2 = p1 / "B" / (std::string() + "C" + ".d"); :D . Оба они работают в godbolt. note that in practice, "C" will most likely На практике нет, в любом случае результат p1 / "B" / "C" имеет тип std::filesystem::path, поэтому он делает с ним +=. Тем не менее, это не ответ, так как я не знаю причины этого несоответствия.   -  person KamilCuk    schedule 27.01.2021
comment
По этой причине, я думаю, кому-то придется заглянуть в список рассылки или что-то подобное. Для возможности назначить/ += для rvalue есть stackoverflow.com/questions/65461889/ . Вызов path() поможет ((path(a) += b)), если объект внутри является lvalue.   -  person user202729    schedule 27.01.2021
comment
@KamilCuk Под «на практике» я имел в виду, в моем реальном приложении. Это упрощенный пример.   -  person Touloudou    schedule 27.01.2021


Ответы (1)


Это немного умозрительно, но я думаю, что причина этого в том, что operator+ можно легко спутать с operator/. Это приведет к ошибкам, если использовать их следующим образом.

path p2{"/"};
auto p1 = p2 + "A" + "B";
// Wants /A/B, gets /AB

Использование строковых литералов делает обходной путь более приятным:

using namespace std::literals;
std::filesystem::path p1{"A"};
auto p2 = p1 / "B" / ("C"s + ".d");   

Здесь "C"s создает std::string с содержимым C, а затем мы используем operator+ std::string. Если часть "C" сама по себе уже является путем (иначе вы могли бы просто написать "C.d" для начала), вы можете сделать

std::filesystem::path p1{"A"}, c_path{"C"};
auto p2 = p1 / "B" / (c_path += ".d");   

так как operator+= возвращает результирующий объект. (Это немного расточительно, но я могу представить, что компилятор это оптимизирует).

person n314159    schedule 27.01.2021