I try to store/load std::chrono::minute
s to/from json using boost::json
s tag_invoke mechanism. While this works well for my custom little struct
, I fail to formulate correct syntax for the chrono
type.
I tried two straightforward versions:
void tag_invoke(boost::json::value_from_tag const&, boost::json::value &value, std::chrono::minutes const &minu);
std::chrono::minutes tag_invoke(boost::json::value_to_tag<std::chrono::minutes> const&, boost::json::value const &value);
and
namespace std::chrono {
void tag_invoke(boost::json::value_from_tag const&, boost::json::value &value, /*std::chrono::*/minutes const &minu);
/*std::chrono::*/minutes tag_invoke(boost::json::value_to_tag</*std::chrono::*/minutes> const&, boost::json::value const &value);
}
Both versions lead to the same compiler errors (g++ 11.3), which include
/.../_deps/boost-src/libs/json/include/boost/json/value_from.hpp:87: error: no matching function for call to ‘value_from_impl(std::chrono::duration<long int, std::ratio<60> >, std::remove_reference<boost::json::storage_ptr&>::type)’
which seems to be the typical marker that my overload is not found/considered.
What is the quirk that I miss here?
You correctly surmised you need to put the declaration in a namespace associated via ADL.
Both the
boost::json
andstd::chrono
work for me:Live On Coliru
Output:
Perhaps with your standard library implementation
std::chrono::minutes
is a typedef for something other (not declared in that exact namespace)? I'm not sure whether the standard allows for that actuallyGeneralize!
Regardless of what you end up doing, I recommend not special casing a particular ratio. Instead generically support all durations!
Live On Coliru
Prints e.g.
Or with
-ffast-math
:No Floating Point?
To reduce the inexact FP representation issue, pick a resolution: http://coliru.stacked-crooked.com/a/c5b8e084b5d47f3f
More strictly, you can outlaw floating point representation in the overload: http://coliru.stacked-crooked.com/a/caca13072524b0f9