sprintf-alloca-style string building for constructors
Monday, May 23, 2011 12:00:00 PM
Ladies and gentlemen, I give you the ext::sprintfa template:
COM::COM (unsigned int index)
: Device (ext::sprintfa <16u> ("\\\\.\\COM%u", index + 1u)) {}
The implementation of the idea should be clear from the synopsis that follows. The displayed use of ext::sprintfa<X> compiles into constructor call of a stack-allocated temporary object. Static buffer (of length X) of this object acts as memory for the resulting string. Pointer to this string is retrieved by implicit conversion to const char *. And the object is automatically destroyed at the end of the expression, that is, after the full chain of constructors finishes.
template <unsigned int _Size>
class ext::sprintfa {
private:
char memory [_Size];
public:
static const unsigned int size = _Size;
public:
sprintfa (const char * format, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
~sprintfa ();
public:
operator const char * ();
const char * operator & ();
};
Users of compilers other than GCC will need to remove the constructor attribute.const char * operator & (); here is a helper function that simplifies passing ext::sprintfa<> instances to functions which take variable number of parameters by simply prefixing it with an ampersand. E.g. printf-family functions or another ext::sprintfa calls.
To make this article complete, the actual implementation may look like this:
template <unsigned int _Size>
ext::sprintfa <_Size> ::sprintfa (const char * format, ...) {
using namespace std;
va_list args;
va_start (args, format);
vsnprintf (this->memory, _Size, format, args);
va_end (args);
return;
};
template <unsigned int _Size>
ext::sprintfa <_Size> ::~sprintfa () {
if (_Size)
this->memory [0] = '\0';
return;
};
template <unsigned int _Size>
ext::sprintfa <_Size> ::operator const char * () {
return this->memory;
};
template <unsigned int _Size>
const char * ext::sprintfa <_Size> ::operator & () {
return this->memory;
};
In real world code you would probably want to use wchar_t/vswprintf. To implement such ext::swprintfa template is left as an exercise to the reader :)

