Skip to content

Instantly share code, notes, and snippets.

@garettbass
Last active January 27, 2020 19:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save garettbass/6ef9a3f0371e026ed643cd284ef0a43a to your computer and use it in GitHub Desktop.
Save garettbass/6ef9a3f0371e026ed643cd284ef0a43a to your computer and use it in GitHub Desktop.
Get the namespace-qualified name of a type without RTTI.
#include <stdint.h>
#include <stdio.h>
#include <string.h>
template<typename T>
const char* typenameof() {
#if defined(__clang__)
enum { header = sizeof("const char *typenameof() [T = ")-1 };
enum { footer = sizeof("]")-1 };
static char buffer[sizeof(__PRETTY_FUNCTION__)-(header+footer)] {};
static const char* const name {
strncpy(buffer,__PRETTY_FUNCTION__+header,sizeof(buffer)-1)
};
#elif defined(__GNUC__)
enum { header = sizeof("const char *typenameof() [with T = ")-1 };
enum { footer = sizeof("]")-1 };
static char buffer[sizeof(__PRETTY_FUNCTION__)-(header+footer)] {};
static const char* const name {
strncpy(buffer,__PRETTY_FUNCTION__+header,sizeof(buffer)-1)
};
#elif defined(_MSC_VER)
enum { header = sizeof("const char *__cdecl typenameof<")-1 };
enum { footer = sizeof(">(void)")-1 };
static char buffer[sizeof(__FUNCSIG__)-(header+footer)] {};
static const char* const name = [&](const char* const funcsig){
const char* itr = funcsig + header;
if (itr == strstr(itr, "enum ")) itr += sizeof("enum");
if (itr == strstr(itr, "class ")) itr += sizeof("class");
if (itr == strstr(itr, "struct ")) itr += sizeof("struct");
const char* const end = strstr(itr, ">(void)");
const size_t size = end - itr;
strncpy_s(buffer,sizeof(buffer),itr,size);
return buffer;
}(__FUNCSIG__);
#endif
return name;
}
namespace example {
enum an_enum {};
enum struct an_enum_struct {};
enum class an_enum_class {};
struct a_struct {};
class a_class {};
} // namespace example
int main() {
#define echo(EXPR) printf(#EXPR": \"%s\"\n", EXPR)
echo(typenameof<int32_t>()); // "int"
echo(typenameof<uint32_t>()); // "unsigned int"
echo(typenameof<example::an_enum>()); // "example::an_enum"
echo(typenameof<example::an_enum_struct>()); // "example::an_enum_struct"
echo(typenameof<example::an_enum_class>()); // "example::an_enum_class"
echo(typenameof<example::a_struct>()); // "example::a_struct"
echo(typenameof<example::a_class>()); // "example::a_class"
}
@garettbass
Copy link
Author

garettbass commented Jan 27, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment