Как правильно добавить дополнительное расширение для boost::filesystem::path?

Я хочу добавить дополнительное расширение к пути:

namespace fs = boost::filesystem;
fs::path append_extension(const fs::path& path, const fs::path& ext);

Ожидаемое поведение:

  • append_extension("foo.txt", ".log") -> "foo.txt.log"
  • append_extension("foo.txt", "log") -> "foo.txt.log"
  • append_extension("foo", "log") -> "foo.log"

Можно ли реализовать append_extension без манипуляций со строками с символом точки?


person Nikerboker    schedule 07.11.2016    source источник
comment
Если вы публикуете пример кода, было бы неплохо сделать его синтаксически правильным.   -  person sehe    schedule 07.11.2016
comment
поможет ли replace_extension?   -  person Brett Hale    schedule 07.11.2016
comment
replace_extension не сохраняет первое расширение. оператор += работает некорректно при отсутствии точки в параметре ext.   -  person Nikerboker    schedule 07.11.2016


Ответы (1)


Как насчет

namespace fs = boost::filesystem;
fs::path append_extension(const fs::path& path, const fs::path& ext) {
    auto sz_ext = ext.c_str();
    if ('.' == *sz_ext) ++sz_ext;
    return path.string<std::string>() + "." + sz_ext;
}

Можно ли реализовать append_extension без манипуляций со строками с символом точки?

Нет. Расширения — это не вещь, это просто соглашения. Вторичные расширения даже не являются соглашением, так что вы сами по себе.

ДЕМО

Прямой эфир на Coliru

#include <boost/filesystem.hpp>
#include <boost/property_tree/string_path.hpp>

namespace fs = boost::filesystem;
fs::path append_extension(const fs::path& path, const fs::path& ext) {
    auto sz_ext = ext.c_str();
    if ('.' == *sz_ext) ++sz_ext;
    return path.string<std::string>() + "." + sz_ext;
}
#include <iostream>

int main() {
    std::cout << append_extension("foo.txt", ".log") << "\n"; // -> "foo.txt.log"
    std::cout << append_extension("foo.txt", "log") << "\n"; // -> "foo.txt.log"
    std::cout << append_extension("foo", "log") << "\n"; // -> "foo.log"
}

Отпечатки

"foo.txt.log"
"foo.txt.log"
"foo.log"
person sehe    schedule 07.11.2016
comment
Ваш ответ выглядит нормально, но он возвращает неожиданный результат (две последовательные точки) для 1-го образца. Обратите внимание, что для метода path::replace_extension можно указать расширение как с точкой, так и без. - person Nikerboker; 07.11.2016
comment
Вы совершенно правы. Конечно, вы можете обнаружить замыкающую точку и заблокировать лишнюю точку. Обновление ответа - person sehe; 07.11.2016
comment
Я почти готов принять, но не могли бы вы объяснить, в чем причина path.string<std::string>()? Почему не path::string()? - person Nikerboker; 07.11.2016
comment
Еще один комментарий: в вашей реализации параметр path может быть объявлен как константная ссылка. - person Nikerboker; 07.11.2016
comment
Ага. Я играл с вариантом, который обновлял его на месте (используя boost::property_tree::string_path<std::string>), но я отказался от него. - person sehe; 07.11.2016
comment
Причина для string<std::string> заключалась в том, что (а) я не знал о перегрузке без шаблона (?) и (б) хорошо знать тот факт, что этот метод подразумевает выбор - person sehe; 07.11.2016