If you need to get name of derived class from base class, then you obviously need virtual function, not static. And to minimize code you need to type just use macro.
Simple way:
#include <iostream>
#include <string_view>
#define DECLARE_GETNAME(X) \
virtual std::string_view getName() { \
return #X; \
}
class Base {
public:
virtual ~Base() = default;
DECLARE_GETNAME(Base)
};
class Derived : public Base{
DECLARE_GETNAME(Derived)
};
int main()
{
Derived d;
Base& b = d;
std::cout << b.getName();
}
If you don't want to type class name every time, you can do it also, but little bit more complicated. Something like that:
#include <iostream>
#include <string_view>
template<typename T>
struct TypeName {
constexpr static std::string_view fullname_intern() {
#if defined(__clang__) || defined(__GNUC__)
return __PRETTY_FUNCTION__;
#elif defined(_MSC_VER)
return __FUNCSIG__;
#else
#error "Unsupported compiler"
#endif
}
constexpr static std::string_view name() {
size_t prefix_len = TypeName<void>::fullname_intern().find("void");
size_t multiple = TypeName<void>::fullname_intern().size() - TypeName<int>::fullname_intern().size();
size_t dummy_len = TypeName<void>::fullname_intern().size() - 4*multiple;
size_t target_len = (fullname_intern().size() - dummy_len)/multiple;
std::string_view rv = fullname_intern().substr(prefix_len, target_len);
if (rv.rfind(' ') == rv.npos)
return rv;
return rv.substr(rv.rfind(' ')+1);
}
using type = T;
constexpr static std::string_view value = name();
};
#define DECLARE_GETNAME() \
virtual std::string_view getName() { \
return TypeName<std::remove_cvref_t<decltype(*this)>>::value; \
}
class Base {
public:
virtual ~Base() = default;
DECLARE_GETNAME()
};
class Derived : public Base{
DECLARE_GETNAME()
};
int main()
{
Derived d;
Base& b = d;
std::cout << b.getName();
}
Code to get type name copied from here: https://stackoverflow.com/a/68139582/11680056