
On 3/06/2014 01:27, quoth Vladimir Batov:
An example of this in another conversion library was one that provided for conversion from std::wstring to const char *. This was handled by having a local instance of a "context" object (possibly analogous to the converter) that internally stored any memory allocated during the course of the conversion, such that the returned pointer remained valid as long as the context object was in scope, and no memory was leaked. [...] Gavin, my humble apologies for answering your post/question that late. Somehow I managed to miss it in the avalanche. Now that I am re-reading the
Gavin Lambert wrote threads, I've come across your post and it made me very excited. You are describing IMO a quite interesting/tricky conversion case that the proposed design (with external converters passed in) handles seemingly with ease. In the proposed design converters are created/configured independently from actual conversion. So, they can store configuration/state. Say, std::sstream-based converter remembers hex/dec/oct/uppercase/locale settings, etc. In the case of std::wstring -> "char const*" that might be as follows:
char buf[...]; my_converter cnv;
optional<char const*> res = convert<char const*>(from, cnv(buf));
Above "cnv(buf)" takes "buf" and uses it during conversion and returns pointer to it if successful. Does it sound like the case you describe? Admittedly, that would not probably my deployment choice but to me it seems to demonstrate the flexibility/adaptability of the design.
No, that's different from what I was describing. The other conversion library internally allocated the required memory (such that it could allocate exactly the right amount). To use the above style, the code would look more like this: std::wstring from1(L"some text"), from2(L"other text"); converter<std::wstring, char const*> cnv; optional<char const*> res1 = convert<char const*>(from1, cnv); optional<char const*> res2 = convert<char const*>(from2, cnv); // pointer values contained in res1 & res2 remain valid as long // as cnv is in scope, and are freed when cnv is destroyed. The main point being that state held within the conversion object is modified as a result of the conversion (specifically, the allocated memory is added to a linked-list to be freed on destruction); thus the converter itself must be a non-const reference. The other thing that was nice about this was that you could obtain the converter generically -- so you could template the method itself and let it accept not just std::wstring but anything that was convertible to char const*, and the appropriate conversion would be automatically selected. Admittedly auto-selecting converters does get trickier if you start to add custom types and multiple possible string representations into the mix, but presumably over time you'd build up "families" of related converters, and the converter family could itself be a template parameter (similar to std::allocator).