template constexpr std::string_view type_name() { // clang: std::string_view ns::type_name() [T = int] // gcc: constexpr std::string_view ns::type_name() [with T = int; std::string_view = std::basic_string_view] // msvc: const char *__cdecl ns::type_name(void) auto substring_bounded_by = [](std::string_view sig, std::string_view l, std::string_view r) { assert(sig.find(l) != std::string_view::npos); assert(sig.rfind(r) != std::string_view::npos); assert(sig.find(l) < sig.rfind(r)); auto i = sig.find(l) + l.length(); return sig.substr(i, sig.rfind(r) - i); }; #if defined(__clang__) return substring_bounded_by(__PRETTY_FUNCTION__, "[T = ", "]"); #elif defined(__GNUC__) || defined(__GNUG__) return substring_bounded_by(__PRETTY_FUNCTION__, "[with T = ", "; std::string_view = "); #elif defined(_MSC_VER) return substring_bounded_by(__FUNCSIG__, "type_name<", ">(void)"); #else // TODO: ? return __PRETTY_FUNCTION__; #endif }