This is another invention of the wheel and horrible but quick solution, basically, exploit the similarity between namespace structure and directory structure.
#include<boost/type_index.hpp>
#include<boost/filesystem/path.hpp>
namespace A{
namespace B{
struct C{};
}
}
int main(){
std::string s = boost::typeindex::type_id_with_cvr<A::B::C const*&>().pretty_name();
replace(begin(s), end(s), ':', '/');
replace(begin(s), end(s), ' ', '.');
using namespace boost::filesystem;
assert( path(s).string() == "A//B//C.const*&" );
assert( path(s).filename() == "C.const*&" );
assert( path(s).extension() == ".const*&" );
assert( path(s).stem() == "C" );
assert( path(s).parent_path() == "A//B");
assert( path(s).parent_path().parent_path() == "A");
}
or package it into a simple ugly class:
#include<boost/type_index.hpp>
#include<boost/filesystem/path.hpp>
namespace A{
namespace B{
struct C{};
}
}
template<class T>
class typename_info_t{
boost::filesystem::path p_;
public:
typename_info_t(){
std::string s = boost::typeindex::type_id_with_cvr<T>().pretty_name();
replace(begin(s), end(s), ':', '/');
replace(begin(s), end(s), ' ', '.');
p_ = s;
}
std::string full_name() const{
std::string s = p_.string();
replace(begin(s), end(s), '/', ':');
replace(begin(s), end(s), '.', ' ');
return s;
}
std::string namespace_name() const{
std::string s = p_.parent_path().string();
replace(begin(s), end(s), '/', ':');
return s;
}
std::string class_name() const{
std::string s = p_.stem().string();
replace(begin(s), end(s), '/', ':');
return s;
}
std::string class_name_with_cvr() const{
std::string s = p_.filename().string();
replace(begin(s), end(s), '/', ':');
replace(begin(s), end(s), '.', ' ');
return s;
}
std::string cvr() const{ // begins with space
std::string s = p_.extension().string();
replace(begin(s), end(s), '.', ' ');
return s;
}
};
template<class TT> typename_info_t<TT> typename_info(){return {};}
int main(){
assert( typename_info<A::B::C const*&>().full_name() == "A::B::C const*&" );
assert( typename_info<A::B::C const*&>().namespace_name() == "A::B" );
assert( typename_info<A::B::C const*&>().class_name() == "C" );
assert( typename_info<A::B::C const*&>().class_name_with_cvr() == "C const*&" );
assert( typename_info<A::B::C const*&>().cvr() == " const*&");
}
(limitation: '*' pointer qualifier is not part of the class name here, unfortunatelly this forces to use #include<boost/filesystem.hpp> or #include<experimental/filesystem> which are non header-only libraries.