rapidyaml: Serialize std::filesystem::path error
Hi how to correctly supply to_chars
overload for std::filesystem::path
?
All my other custom types work by overloading write
or to_chars
but with filesystem::path I always get a compile error which says that it somehow does not find a matching function. What am I doing wrong?
#include <filesystem>
#define RYML_SINGLE_HDR_DEFINE_NOW
#include "rapidyaml.hpp"
size_t to_chars(ryml::substr buf, std::filesystem::path const& p) {
return to_chars(buf, p.generic_string());
}
int main(int argc, char** argv)
{
std::filesystem::path path = "C:/sample";
ryml::Tree tree{};
ryml::NodeRef root = tree.rootref();
root << path;
return 0;
}
./rapidyaml.hpp:19835:22: error: no matching function for call to 'to_chars'
19835 | size_t num = to_chars(rem, a);
| ^~~~~~~~
./rapidyaml.hpp:21107:29: note: in instantiation of function template specialization 'c4::yml::Tree::to_arena<std::filesystem::path>' requested here
21107 | csubstr s = m_tree->to_arena(v);
| ^
./rapidyaml.hpp:21561:8: note: in instantiation of function template specialization 'c4::yml::NodeRef::set_val_serialized<std::filesystem::path>' requested here
21561 | n->set_val_serialized(v);
| ^
./rapidyaml.hpp:21233:9: note: in instantiation of function template specialization 'c4::yml::write<std::filesystem::path>' requested here
21233 | write(this, v);
| ^
main.cpp:22:7: note: in instantiation of function template specialization 'c4::yml::NodeRef::operator<<<std::filesystem::path>' requested here
22 | root << path;
About this issue
- Original URL
- State: closed
- Created 3 months ago
- Comments: 16 (8 by maintainers)
Finally found what’s wrong: ADL (AKA Koenig lookup) fails because of a missing namespace.
You need to declare the
to_chars()
overload in one of the namespaces: eitherstd::filesystem
orc4
orc4::yml
.So this will work:
and this as well:
… and this as well:
I’ve had to face this problem several times before. This time I forgot all about it, apparently… Also, if you look for example at the
to_chars()
implementation forstd::string
, you’ll notice thatto_chars()
is underc4
. That is the hint on how to do it.So you can use the clean version of the header, provided you define
to_chars()
in one of the three namespaces above.Note that unfortunately you cannot use
ryml
, becauseryml
is an importing namespace forc4::yml
:As for adding
std::filesystem::path
to the library’s default std helpers, that’s unfortunately not possible because of the generic vs native question. If it were added, one of the two would be have to be forced on the users, and that’s not a legitimate thing for a library like this.Also, let me point out that if the reason you’re using
std::filesystem::path
is merely for path manipulation, it may be that you can just use thecsubstr
class, which provides Path-like manipulation methods (search for Path-like in that link), and spares you the inherent allocation inp.generic_string()
.Yes I think it makes sense to add fs::path with other provided overloads the only question would be which format to choose. Keep backslashes on windows or convert to forward slashes with
generic_string()
.Anyway, I’ve added a few lines inside the header and it works for me as a workaround for now. The library overall is really pleasant to use btw!