Neither one nor Many
Software engineering blog about my projects, geometry, visualization and music.
This is no rocket science but I thought this was a really cool solution to the problem.
First I created a helper function Xprintf to interface with an existing C API that works with (non const) char arrays. Hence its char * return value.
char *Xprintf(const char *format, ...);
// This function works in the following situations
foo1(Xprintf("Hello world: %d", 1001)); // void foo1(char *);
foo2(Xprintf("Hello world: %d", 1001)); // void foo2(const char *);
foo3(Xprintf("Hello world: %d", 1001)); // void foo3(const string);
foo4(Xprintf("Hello world: %d", 1001)); // void foo4(const string &);
foo5(Xprintf("Hello world: %d", 1001),
Xprintf("...", ...)); // void foo5(char *, char *);
Xprintf cannot use just one buffer because the case of 'foo5' would fail (it would get the same pointer twice).
I needed a different return value, like std::string, so that copies could be returned which would clean themselves up as soon as they went out of scope.
But std::string does not provide implicit casting to const char *, only explicit casting through .c_str().
The call to foo1 would become: foo1(const_cast
The following fixes it, creating a tmp_str class that extends std::string and simply provides the implicit cast:
class tmp_str : public std::string
{
public:
tmp_str(const char *str)
: std::string(str) {}
// g++ is fine with adding this one, xlC isn't
//operator const char *() const { return c_str(); }
operator char *() const { return const_cast<char *>(c_str()); }
};
tmp_str cHelperCharArray::Xprintf(const char *format, ...)
{
char buffer[512] = {0x00};
va_list args;
va_start(args, format);
vsprintf(buffer, format, args);
va_end(args);
return tmp_str(buffer);
}
A note why tmp_str is-a std::string and not an is-implemented-in-terms-of: the call to foo4 would fail as it would not accept tmp_str as a reference to string (A parameter of type "const std::basic_string,std::allocator > &" cannot be initialized with an rvalue of type "tmp_str".). )
g++ accepts all these foo* functions, but IIRC xlC doesn't like foo2. In that case I had to cast to const. Adding the const char * operator overload would make some casts for that compiler ambiguous.