4

So std::map wants the key type to be ordered, but I ran into problems:

"a/b" < "a/c" < "a//b" but fs::equivalent("a/b", "a//b")

"a/b" < "a/c" < "a\b" but fs::equivalent("a/b", "a\b")

How I do I normalize a path enough to create an ordering? Is that even possible? I tried using path::generic_string() in a custom comparison operator, but it didn't work. fs::equivalent() doesn't help either, because implementing equality isn't enough for std::map, it needs an ordering. That's also the reason why this question isn't a duplicate of How do I "normalize" a pathname using boost::filesystem?.

Context: Windows only, Boost 1.49, filesystem3.

Community
  • 1
  • 1
Andreas Haferburg
  • 5,189
  • 3
  • 37
  • 63

1 Answers1

2

To make paths comparable you need to convert them to the canonical representation and then compare via string. A canonical path is absolute, normalized and has symbolic links removed. Boost offers canonical AFAIK. Because symbolic links need to be resolved, calling canonical requires access to the filesystem.

Christopher Oezbek
  • 23,994
  • 6
  • 61
  • 85
  • 1
    Nope: fs::canonical(fs::path("C:\\Temp\\boost\\test.txt")) -> "C:/Temp\boost\test.txt", but fs::canonical(fs::path("c:/temp//boost/test.txt")) -> "c:/temp\boost\test.txt". – Andreas Haferburg Dec 07 '12 at 14:10
  • Well, upon closer inspection, I guess it does everything I need except change the case. So boost::to_lower_copy(fs::canonical(path).string()) should do the trick. – Andreas Haferburg Dec 07 '12 at 14:23
  • 2
    Too bad that boost::fs does not tell you whether the fs is case-sensitive or not. – Christopher Oezbek Dec 07 '12 at 14:32