Is there interest in typeid(TYPE).name() like function that does not require RTTI

Hi, Would be there some interest in function for getting class name without RTTI? Such function can be implemented like that: template <class TemplateNameT> std::string template_type(const TemplateNameT& v) { #ifdef _MSC_VER const char* const template_name_begin = strstr(BOOST_CURRENT_FUNCTION, "(const ") + sizeof("(const ") - 1; BOOST_ASSERT(template_name_begin); const char* const template_name_end = template_name_begin + strlen(template_name_begin) - sizeof("&)"); #else // Code for other platforms #endif return std::string(template_name_begin, template_name_end); } If there is some interest, I'll update code to work on other platforms, and change method signature from template_type(instance) to template_type<InstanceTypeT>::name() Usage example: // Function can be compiled with RTTI disabled. template <class T> void foo(const T& val) { std::cerr << template_type<T>::name(); // instead of typeid(T).name(); } -- Best regards, Antony Polukhin

Antony Polukhin wrote:
Would be there some interest in function for getting class name without RTTI?
Boost.Exception has such a function boost::type_name in <boost/exception/detail/type_info.hpp>. Personally, I'm using the following code. This code is useful because it does not strip off cv- or ref-qualifiers (e.g. boost::type_name<int const&>() --> "int const&"). #include <string> #include <boost/config.hpp> #ifndef BOOST_NO_TYPEID #include <boost/units/detail/utility.hpp> #else #include <boost/current_function.hpp> #endif namespace boost { namespace type_name_detail { #ifndef BOOST_NO_TYPEID template <typename T> struct demangle_impl { static std::string apply() { return boost::units::detail::demangle(typeid(T).name()); } }; template <typename T> struct demangle_impl<T const> { static std::string apply() { return demangle_impl<T>::apply() + " const"; } }; template <typename T> struct demangle_impl<T volatile> { static std::string apply() { return demangle_impl<T>::apply() + " volatile"; } }; template <typename T> struct demangle_impl<T const volatile> { static std::string apply() { return demangle_impl<T>::apply() + " const volatile"; } }; template <typename T> struct demangle_impl<T&> { static std::string apply() { return demangle_impl<T>::apply() + "&"; } }; #ifndef BOOST_NO_RVALUE_REFERENCES template <typename T> struct demangle_impl<T&&> { static std::string apply() { return demangle_impl<T>::apply() + "&&"; } }; #endif #endif } // namespace type_name_detail template <typename T> inline std::string type_name() { #ifndef BOOST_NO_TYPEID return type_name_detail::demangle_impl<T>::apply(); #else return BOOST_CURRENT_FUNCTION; #endif } } // namespace boost Regards, Michel

2012/5/30 Michel Morin <mimomorin@gmail.com>:
When RTTI disabled, you are returning whole function name, not just the required type T. In your case you`ll get somethihg like ‘std::string boost::type_name() [with T = const int&, std::string = std::basic_string<char>]’ instead of 'const int&'. There is also a detail/sp_typeinfo.hpp header, which provides almost what I propose. But it is undocumented, creates additional static variables for each template instance, produces long names(like from example above), noncopyable. May be we shall document sp_typeinfo.hpp, move it to utility, and implement it via temple_info<T> class, which would be copyable? -- Best regards, Antony Polukhin

Antony Polukhin wrote:
On VC++ with /GR option, we can still use `typeid` (though we cannot use it to obtain the dynamic type of polymorphic types). But, yeah, we get the whole function names if BOOST_CURRENT_FUNCTION is used. Now I understand what you're trying to do and I'm definitely interested in it! If there is a reliable way to extract type names from BOOST_CURRENT_FUNCTION, this is very useful. Clang-3.1 has gcc-like __PRETTY_FUNCTION__. But, on clang-3.0 and the prior versions, __PRETTY_FUNCTION__ is less usefull. It does not contain type names of template arguments for function templates. So we have to extract type names from function arguments: template <typename T> const char * f() { return BOOST_CURRENT_FUNCTION; } template <typename T> const char * g(const T&) { return BOOST_CURRENT_FUNCTION; } f<int>() --> const char *f() g(0) --> const char *g(const int &) Thanks for interesting stuff, Antony! Regards, Michel

Hi Antony,
Hi,
Would be there some interest in function for getting class name without RTTI?
We've been using similar solutions for unit testing template metaprograms (Mpllibs.Metamonad, Mpllibs.Metaparse). For example when we test that evaluating "metafunction_to_test<mpl::int_<13> >::type" gives "mpl::int_<11>" as the result, the testing code looks like the following: mpl::equal_to<mpl::int_<11>, metafunction_to_test<mpl::int_<13> >::type> we give the code to the metaprogramming testing framework in Mpllibs.Metatest that evaluates it and when it fails, generates code pretty-printing the above angly-bracket expression. That pretty-printed expression (and the result of the test) can be given to some unit testing framework (Metatest's own, Boost.Test, CppUnit, etc.) that displays it. Given that the above code enforces the evaluation of "metafunction_to_test<mpl::int_<13> >" this solution can generate error reports like: mpl::equal_to<mpl::int_<11>, mpl::int_<20>> which can be really helpful for metaprogram development. Getting class names could help with type pretty-printing, however, metaprogramming library authors should be able to override it (eg. pretty-printing an mpl::vector should give something like "vector<int, char>" instead of the internals of vector's implementation). We have created a template class (mpllibs::metatest::to_stream) for type pretty-printing in Mpllibs.Metatest, but it needs further improvements. It is specialised for a number of types and prints "???" for the rest. We tried to use RTTI as well but: - it enforced the evaluation of otherwise unevaluated lazy metaprogramming expressions - it didn't give readable output (for metaprograms) So a way of getting a class name could improve this solution. All the code I'm talking about is in the following git repository: https://github.com/sabel83/mpllibs Regards, Ábel

2012/5/30 Abel Sinkovics <abel@elte.hu>:
I`ve implemented an almost full featured type_info that does not use RTTI and returns pretty-printing names. Now you can use it like: typedef mpl::equal_to<mpl::int_<11>, metafunction_to_test<mpl::int_<13> >::type> mpl_eq_lazy_result; std::cout << get_template_info<mpl_eq_lazy_result>().name_demangled(); // shall output boost::mpl::equal_to<mpl_::int_<11>, mpl_::int_<20> > on MSVC I`ve started a new thread called '[boost] Is there interest in copyable type_info that does not require RTTI (was: Is there interest in typeid(TYPE).name() like function that does not require RTTI)', I`ll clean up the code and commit it at this or next week. -- Best regards, Antony Polukhin

On 29 May 2012 14:29, Antony Polukhin <antoshkka@gmail.com> wrote:
Would be there some interest in function for getting class name without RTTI?
To be clear, this does not do the same thing as RTTI. For instance: struct B { virtual ~B() {} }; struct D : B {}; // ... D d; B& b(d); std::cout << template_type(b) << std::endl; will print B, not D. That being said, this is mighty useful, especially when doing non-trivial things with templates. Now, I'd rather the interface return some kind of range, as there are many times I don't want to pay the allocation cost for putting it in a string. -- Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404

2012/5/30 Nevin Liber <nevin@eviloverlord.com>:
Yeep, you`ve got it!
I was implementing const char* raw_name() and std::string name_demangled(). First returns zero terminated character sequence that contains not very nice names: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::name_begin(void) or std::basic_string<char>] Second returns more user friendly nice printable name: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > or std::basic_string<char> Any more feature requests? -- Best regards, Antony Polukhin
participants (4)
-
Abel Sinkovics
-
Antony Polukhin
-
Michel Morin
-
Nevin Liber