path lexically_relative(const path& base) const;
概要
文字列レベルで相対パスに変換する。
この関数は、*thisが保持するパス文字列を、パスbaseからの相対パスに変換する。ただし、この関数ではファイルシステムを介さず文字列レベルで相対パスへの変換をするため、相対パスを解決できない場合がある。相対パスが解決できなかった場合は、空のパスが返る。ファイルシステムを介した相対パスへの変換を行う場合は、std::filesystem::relative()関数を使用すること。
効果
- 以下のいずれかの条件に一致する場合、相対パスの解決ができず、空のパスが返る:
root_name() != base.root_name()is_absolute() != base.is_absolute()!has_root_directory() && base.has_root_directory()relative_path()またはbase.relative_path()のいずれかのファイル名が、ルート名として解釈できる場合(Windowsのように、ファイル名がルート名になりうる環境での誤った解決を防ぐため)
- 以下の式で、
*thisとbaseが異なる最初の位置を見つける:auto [a, b] = std::mismatch(begin(), end(), base.begin(), base.end());
a == end()かつb == base.end()の場合、path(".")が返る- イテレータ範囲
[b, base.end())の非"."(ドットx1) かつ非".."(ドットx2) かつ非空 (empty) の要素の数から、同範囲内の".."の数を引いたものをnとする n < 0であれば、空のパスが返るn == 0かつ(a == end()|| a->empty())の場合、path(".")が返る- 新たな
path型オブジェクトpをデフォルト構築し、 - 式
p /= path("..")をn回を適用する - イテレータ範囲
[a, end())の各要素xを、式p /= xで加算する
備考
- この関数は、
*thisとbaseのどちらに対してもパスの正規化を行わない。必要であれば、どちらか、もしくは両方にlexically_normal()メンバ関数を適用すること
例
#include <cassert>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
assert(fs::path("/a/d").lexically_relative("/a/b/c") == "../../d");
assert(fs::path("/a/b/c").lexically_relative("/a/d") == "../b/c");
assert(fs::path("a/b/c").lexically_relative("a") == "b/c");
assert(fs::path("a/b/c").lexically_relative("a/b/c/x/y") == "../..");
assert(fs::path("a/b/c").lexically_relative("a/b/c") == ".");
assert(fs::path("a/b").lexically_relative("c/d") == "../../a/b");
}
出力
バージョン
言語
- C++17
処理系
- Clang:
- GCC: 8.1 ✅
- Visual C++: 2017 Update 7 ✅
参照
- LWG Issue 3070.
path::lexically_relativecauses surprising results if a filename can also be a root-name- C++20で、相対パス・基準パスのファイル名がルート名として解釈できる場合に空のパスを返す条件が追加され、Windowsのような環境での誤った解決が防がれた
- LWG Issue 3096.
path::lexically_relativeis confused by trailing slashes- C++20で、末尾スラッシュ(空要素)を含むパスで結果が破綻する問題が修正された。要素数の集計から空要素を除外し、
n == 0かつ末尾が空要素の場合にpath(".")を返すステップが追加された
- C++20で、末尾スラッシュ(空要素)を含むパスで結果が破綻する問題が修正された。要素数の集計から空要素を除外し、