
Of course I have no issue, when .to() and .append_to() resort to a free function, that can be overloaded using ADL, like you had proposed:
If member functions are resolving to ADL free functions via a function object, I'm fully ok with that.
Is there a problem for ADL, when stringify_to() is a template on the string factory?
Yes unfortunately. The template has the name `boost::stringify_to` regardless of the types. But if you go via a template functor object that uses ADL to find the free function, then the free function does not have to be a template function, and ADL will work as expected. In order to make the free function non-template you need to pass some trivial identifier from the function's namespace as an argument. So you'll need a tag type. so: namespace boost { template<class Tag> string_factory { using type = typename Tag::type; type operator()(joiner const& j) const { return stringify_to(Tag(), j); } }; } which gets syntactically nasty. which is why we have names like to_string(), hash_code() and so on... :) On 26 January 2017 at 18:08, Christof Donat <cd@okunah.de> wrote:
Hi,
This is not the boost way (see boost::hash), and for good reason.
Well, the extension points to boost::spirit work by specializing e.g. is_contaner<>, or is_string<>. See http://www.boost.org/doc/libs/ 1_61_0/libs/spirit/doc/html/spirit/advanced/customize/is_container.html That is the same for traits in the standard library, so it actually is a common pattern. I understand, that e.g. std::swap does it the way, you propose.
Am 26.01.2017 15:04, schrieb Richard Hodges:
Template specialisations of free functions are always a bad idea - they
don't play nicely with ADL. So I would not recommend convert<std::string>(join(...)) etc.
Please elaborate more on that. I can't see it.
imagine: [...] now someone wishes to provide their own converter, not in the boost namespace:
Actually I prefer to define a concept for targets of something like convert(). The generic convert() then just works with that concept. Then only users, who want to write to something, that does not fulfill the concept. We might also provide a few specializations like char*, that do not obey to the defined concept.
Actually I'd avoid the word "convert" here, because I'd use convert() for a function, that returns a string factory to convert a single value. Other than concat(), the "string factory" returned by convert() will be able to convert in different ways, similar to boost::lexical_cast<>. Currently my favorite API looks like this:
auto i = convert("42"s).to<int>(); // i = 42 // convert can convert from string to objects as well, like lexical_cast
auto s = convert(i).to<std::string>(); // s == "42" hex(i).to(s); // s == "2A" convert(23).to(s); // s = "23" // convert(), hex(), and similar functions return string factories.
append(concat(" - the hex representation of ", i, " is ", hex(i))).to(s); // s = "23 - the hex representation of 42 is 2A" concat("the hex representation of ", i, " is ", hex(i)).to(s); // s = "the hex representation of 42 is 2A" append(" Yeah!").to(s); // s = "the hex representation of 42 is 2A Yeah!"
auto my_numbers = std::vector<int>{11, 12, 13, 14, 15}; join(separator(", "), my_numbers).to(s); // s = "11, 12, 13, 14, 15" join(separator(", "), std::begin(my_numbers), std::end(my_numbers)).to(s); // s = "11, 12, 13, 14, 15" join(separator(", "), my_numbers | hex).to(s); // s = "B, C, D, E, F" // join() works with iterator pairs, ranges and range expressions
append(format(" - the hex representation of {2} is {1}", hex(i), i)).to(s); // s = "B, C, D, E, F - the hex representation of 42 is 2A" format("the hex representation of {2} is {1}", hex(i), i).to(s); // s = "the hex representation of 42 is 2A"
auto v = hex(i).to<std::vector<char>>(); // v == {'2', 'A'} append(convert(i)).to(v); // v == {'2', 'A', '4', '2'}
It almost reads like English cluttered with some weird punctuation. Of course I have no issue, when .to() and .append_to() resort to a free function, that can be overloaded using ADL, like you had proposed:
class string_factory { public: // ...
template <typename TargetT> auto to(TargetT& t) -> TargetT& { return stringify_to(*this, t); }; template <typename TargetT> auto to() -> TargetT { TargetT r; to(r); return r; }; };
Is there a problem for ADL, when stringify_to() is a template on the string factory?
template <typename StringFactory> myTargetType& stringify_to(StringFactory& f, myTargetType& t) { // ... }
Then we can avoid virtual function calls in the string factory.
Christof
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman /listinfo.cgi/boost