1

I wrote a tiny class which relies on boost::json to serialize itself. It fails to compile since compiler sounds to fail finding tag_invoke() functions which implement json::value<=>myClass translation :

/usr/include/boost/json/value_from.hpp:87:35: error: no matching function for call to ‘value_from_impl(CSpicaFTConfig&, std::remove_reference<boost::json::storage_ptr&>::type)’
 return detail::value_from_impl(
        ~~~~~~~~~~~~~~~~~~~~~~~^
     std::forward<T>(t), std::move(sp));

An implementation of those 2 functions is given:

CSpicaFTConfig CSpicaFTConfig::tag_invoke(value_to_tag<CSpicaFTConfig>, value const &jv);
void CSpicaFTConfig::tag_invoke(value_from_tag, value &jv, CSpicaFTConfig const &cfg);

But compiler seems to be unable to find them.

Any hints are welcome ! Thanks

sehe
  • 374,641
  • 47
  • 450
  • 633
sylwa06
  • 77
  • 10
  • 1
    Please include the minimal, self contained example. Because **obviously** the error is in there. We can just show the fixed code. – sehe Sep 09 '21 at 18:47
  • 1
    Did you remeber to the make the methods static friends? See this example https://stackoverflow.com/a/66710533/85371 – sehe Sep 09 '21 at 18:48
  • Thanks, yes, tag_invoke() functions should be implemented as free freind external functions. – sylwa06 Sep 10 '21 at 07:50
  • The class-name qualification (`CSpicaFTConfig::`) implies that they're not _free_ functions. And that's not required/recommended anyways. Probably the best is to declare the static friend functions _inline_ (inside the class). Marking a function `friend` inline automatically makes it `static` anyways, so that it behaves as a free function logically, except (1) ADL will find the functions (2) their inline declarations express that they're part of the class interface. – sehe Sep 10 '21 at 09:26
  • Thanks for your help. Yes, you're right : see my own anwser to the ticket below. I declared tag_invoke() functions as CSpicaFTConfig class friend in the CSpicaFTConfig header, but gave them an implementation outside the CSpicaFTConfig namespace. It works fine. – sylwa06 Sep 10 '21 at 14:56

1 Answers1

1

Actually, the proper way to implement tag_invoke() functions is to define them as free functions, friends of the object class (here it is CSpicaFTConfig ) to serialize:

  // CSpicaFTConfig => boost::json::value
  friend void tag_invoke(value_from_tag, value &jv, CSpicaFTConfig const &cfg);
  // boost::json::value => CSpicaFTConfig
  friend CSpicaFTConfig tag_invoke(value_to_tag<CSpicaFTConfig>, value const &jv);

Thanks for your support.

sylwa06
  • 77
  • 10