A little prototype for an idea I had to use some C++11 features to make printf a bit more safe.
#include <initializer_list>
#include <stdio.h>
struct val_t {
enum type_t {
e_int,
e_float,
e_cstr
} type_;
union {
int int_;
float float_;
const char * cstr_;
};
val_t( int v ) : type_( e_int ), int_ ( v ) {}
val_t( float v ) : type_( e_float ), float_( v ) {}
val_t( const char * v ) : type_( e_cstr ), cstr_ ( v ) {}
};
bool print( const char * fmt, std::initializer_list<val_t> vargs ) {
// itterate over the strings
for ( ; *fmt;fmt++ ) {
// check for format specifier
if ( *fmt == '%' ) {
// argument index
int index = fmt[1] - '0';
if (index < 0 || index >= int(vargs.size()))
return false;
// access argument
const val_t & v = vargs.begin()[index];
switch (v.type_) {
case (val_t::e_int ): printf("%d", v.int_ ); break;
case (val_t::e_float): printf("%f", v.float_ ); break;
case (val_t::e_cstr ): printf("%s", v.cstr_ ); break;
default:
return false;
}
// skip argument index
fmt++;
}
else {
// output character
putchar(*fmt);
}
}
return true;
}
int main( void ) {
print( "%0 and %1, %0, %2", { 3, 0.1f, "hello world" } );
getchar();
return 0;
}
The output is:
3 and 0.100000, 3, hello world