#include <string>
#include <sstream>
#include <concepts>
template < typename T > // output_streamable type - an object of type T can be sent to std::ostream
concept output_streamable = requires( std::ostream& stm, const T& v )
{ { stm << v } -> std::same_as<std::ostream&> ; } ;
template < output_streamable T > std::string to_cpp_string( const T& value ) {
std::ostringstream ss;
ss << value;
return ss.str();
}
// returns a pointer to a null-terminated character string owned by the function.
// the string will be overwritten on each invocation of the function. not thread-safe.
template < output_streamable T > constchar* to_c_string( const T& value ) {
static std::string text ;
text = to_cpp_string(value) ;
return text.c_str() ;
}
extern"C" // callable from C
{
// returns a pointer to a null-terminated character string owned by the library.
// the string will be overwritten on each invocation of the function. not thread-safe.
constchar* as_cstri( int v ) { return to_c_string(v) ; }
constchar* as_cstru( unsignedint v ) { return to_c_string(v) ; }
constchar* as_cstrll( longlong v ) { return to_c_string(v) ; }
constchar* as_cstrd( double v ) { return to_c_string(v) ; }
// etc. for each type we want to support
}
I have to mention that I'm trying to make it as a single callable C function.. perhaps using variadic macros (if possible) or detect the type in C and call the right function?
I'm also thinking of adding a callable C function using cpp's typeid..
The user should be put any variable type in C (C99) and will be converted to string.
If you are using GCC and are willing to rely on language extensions you can make do with a combination of __builtin_choose_expr, typeof and __builtin_types_compatible_p. https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
Otherwise I don't think there is a mechanism to do this in C99.