#ifndef BOOST_CORE_TYPE_NAME_HPP_INCLUDED #define BOOST_CORE_TYPE_NAME_HPP_INCLUDED // MS compatible compilers support #pragma once #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif // std::string boost::core::type_name() // // Copyright 2021 Peter Dimov // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include #include #include #include #include #include #include #include #include #include #include #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) # include #endif namespace boost { namespace core { namespace detail { // tn_identity template struct tn_identity { typedef T type; }; // tn_remove_prefix inline bool tn_remove_prefix( std::string& str, char const* prefix ) { std::size_t n = std::strlen( prefix ); if( str.substr( 0, n ) == prefix ) { str = str.substr( n ); return true; } else { return false; } } #if !defined(BOOST_NO_TYPEID) // typeid_name inline std::string fix_typeid_name( char const* n ) { std::string r = boost::core::demangle( n ); #if defined(_MSC_VER) tn_remove_prefix( r, "class " ); tn_remove_prefix( r, "struct " ); tn_remove_prefix( r, "enum " ); #endif // libc++ inline namespace if( tn_remove_prefix( r, "std::__1::" ) ) { r = "std::" + r; } // libstdc++ inline namespace if( tn_remove_prefix( r, "std::__cxx11::" ) ) { r = "std::" + r; } #if defined(BOOST_MSVC) && BOOST_MSVC == 1600 // msvc-10.0 puts TR1 things in std::tr1 if( tn_remove_prefix( r, "std::tr1::" ) ) { r = "std::" + r; } #endif return r; } template std::string typeid_name() { return fix_typeid_name( typeid(T).name() ); } // template names template std::string class_template_name() { #if defined(BOOST_GCC) std::string r = typeid_name(); #else std::string r = typeid_name(); #endif return r.substr( 0, r.find( '<' ) ); } template std::string sequence_template_name() { return detail::class_template_name(); } template std::string set_template_name() { return detail::class_template_name(); } template std::string map_template_name() { return detail::class_template_name(); } template std::string array_template_name() { return detail::class_template_name(); } #else // #if !defined(BOOST_NO_TYPEID) template std::string typeid_name() { return "_Tp"; } template std::string class_template_name() { return "_Tm"; } template std::string sequence_template_name() { return "_Sq"; } template std::string set_template_name() { return "_St"; } template std::string map_template_name() { return "_Mp"; } template std::string array_template_name() { return "_Ar"; } #endif // tn_to_string #if defined(BOOST_MSVC) # pragma warning( push ) # pragma warning( disable: 4996 ) #endif inline std::string tn_to_string( std::size_t n ) { char buffer[ 32 ]; std::sprintf( buffer, "%lu", static_cast< unsigned long >( n ) ); return buffer; } #if defined(BOOST_MSVC) # pragma warning( pop ) #endif // tn_holder template struct tn_holder { static std::string type_name( std::string const& suffix ) { return typeid_name() + suffix; } }; // integrals template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "bool" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "char" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "signed char" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "unsigned char" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "short" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "unsigned short" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "int" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "unsigned" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "long" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "unsigned long" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "long long" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "unsigned long long" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "wchar_t" + suffix; } }; #if !defined(BOOST_NO_CXX11_CHAR16_T) template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "char16_t" + suffix; } }; #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "char32_t" + suffix; } }; #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "char8_t" + suffix; } }; #endif #if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::byte" + suffix; } }; #endif // floating point template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "float" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "double" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "long double" + suffix; } }; // void template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "void" + suffix; } }; // nullptr_t #if !defined(BOOST_NO_CXX11_NULLPTR) template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::nullptr_t" + suffix; } }; #endif // cv template struct tn_holder { static std::string type_name( std::string const& suffix ) { return tn_holder::type_name( " const" + suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return tn_holder::type_name( " volatile" + suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return tn_holder::type_name( " const volatile" + suffix ); } }; // refs template struct tn_holder { static std::string type_name( std::string const& suffix ) { return tn_holder::type_name( "&" + suffix ); } }; #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template struct tn_holder { static std::string type_name( std::string const& suffix ) { return tn_holder::type_name( "&&" + suffix ); } }; #endif // function types #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) // tn_add_each template int tn_add_each_impl( std::string& st ) { if( !st.empty() ) st += ", "; st += tn_holder::type_name( "" ); return 0; } template std::string tn_add_each() { std::string st; typedef int A[ sizeof...(T) + 1 ]; (void)A{ 0, tn_add_each_impl( st )... }; return st; } template std::string function_type_name( tn_identity, std::string const& trailer, std::string const& suffix ) { std::string r = tn_holder::type_name( "" ); if( !suffix.empty() ) { r += '('; if( suffix[ 0 ] == ' ' ) { r += suffix.substr( 1 ); } else { r += suffix; } r += ')'; } r += '(' + tn_add_each() + ')'; r += trailer; return r; } template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), "", suffix ); } }; #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " volatile", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const volatile", suffix ); } }; #endif #if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " &", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const &", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " volatile &", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const volatile &", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " &&", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const &&", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " volatile &&", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const volatile &&", suffix ); } }; #endif #if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " volatile noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const volatile noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " & noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const & noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " volatile & noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const volatile & noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " && noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const && noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " volatile && noexcept", suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const volatile && noexcept", suffix ); } }; #endif #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) // pointers template struct tn_holder { static std::string type_name( std::string const& suffix ) { return tn_holder::type_name( "*" + suffix ); } }; // arrays template std::pair array_prefix_suffix( tn_identity ) { return std::pair( tn_holder::type_name( "" ), "" ); } template std::pair array_prefix_suffix( tn_identity ) { std::pair r = detail::array_prefix_suffix( tn_identity() ); r.second = '[' + tn_to_string( N ) + ']' + r.second; return r; } template std::string array_type_name( tn_identity, std::string const& suffix ) { std::pair r = detail::array_prefix_suffix( tn_identity() ); if( suffix.empty() ) { return r.first + "[]" + r.second; } else { return r.first + '(' + suffix + ")[]" + r.second; } } template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::array_type_name( tn_identity(), suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::array_type_name( tn_identity(), suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::array_type_name( tn_identity(), suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::array_type_name( tn_identity(), suffix ); } }; template std::string array_type_name( tn_identity, std::string const& suffix ) { std::pair r = detail::array_prefix_suffix( tn_identity() ); if( suffix.empty() ) { return r.first + r.second; } else { return r.first + '(' + suffix + ")" + r.second; } } template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::array_type_name( tn_identity(), suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::array_type_name( tn_identity(), suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::array_type_name( tn_identity(), suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::array_type_name( tn_identity(), suffix ); } }; // pointers to members template struct tn_holder { static std::string type_name( std::string const& suffix ) { return tn_holder::type_name( ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); } }; #if defined(BOOST_MSVC) && BOOST_MSVC < 1900 && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), "", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " volatile", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); } }; template struct tn_holder { static std::string type_name( std::string const& suffix ) { return detail::function_type_name( tn_identity(), " const volatile", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); } }; #endif // strings template class L, class Ch> struct tn_holder< L, std::allocator > > { static std::string type_name( std::string const& suffix ) { std::string tn = sequence_template_name< L, std::allocator > >(); return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::string" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::wstring" + suffix; } }; #if !defined(BOOST_NO_CXX11_CHAR16_T) template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::u16string" + suffix; } }; #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::u32string" + suffix; } }; #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L template<> struct tn_holder< std::basic_string > { static std::string type_name( std::string const& suffix ) { return "std::u8string" + suffix; } }; #endif // string views (et al) template class L, class Ch> struct tn_holder< L > > { static std::string type_name( std::string const& suffix ) { std::string tn = sequence_template_name< L > >(); return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; } }; // needed for libstdc++ template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::ostream" + suffix; } }; #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::string_view" + suffix; } }; template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::wstring_view" + suffix; } }; #if !defined(BOOST_NO_CXX11_CHAR16_T) template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::u16string_view" + suffix; } }; #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) template<> struct tn_holder { static std::string type_name( std::string const& suffix ) { return "std::u32string_view" + suffix; } }; #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L template<> struct tn_holder< std::basic_string_view > { static std::string type_name( std::string const& suffix ) { return "std::u8string_view" + suffix; } }; #endif #endif // class templates #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template class L, class... T> struct tn_holder< L > { static std::string type_name( std::string const& suffix ) { std::string tn = detail::class_template_name< L >(); std::string st = tn_add_each(); return tn + '<' + st + '>' + suffix; } }; #else template class L, class T1> struct tn_holder< L > { static std::string type_name( std::string const& suffix ) { std::string tn = detail::class_template_name< L >(); return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; } }; template class L, class T1, class T2> struct tn_holder< L > { static std::string type_name( std::string const& suffix ) { std::string tn = detail::class_template_name< L >(); return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; } }; #endif // sequence containers template class L, class T> struct tn_holder< L > > { static std::string type_name( std::string const& suffix ) { std::string tn = detail::sequence_template_name< L > >(); return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; } }; // set template class L, class T> struct tn_holder< L, std::allocator > > { static std::string type_name( std::string const& suffix ) { std::string tn = detail::set_template_name< L, std::allocator > >(); return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; } }; // map template class L, class T, class U> struct tn_holder< L, std::allocator > > > { static std::string type_name( std::string const& suffix ) { std::string tn = detail::map_template_name< L, std::allocator > > >(); return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; } }; #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) // unordered_set template class L, class T> struct tn_holder< L, std::equal_to, std::allocator > > { static std::string type_name( std::string const& suffix ) { std::string tn = detail::set_template_name< L, std::equal_to, std::allocator > >(); return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; } }; // unordered_map template class L, class T, class U> struct tn_holder< L, std::equal_to, std::allocator > > > { static std::string type_name( std::string const& suffix ) { std::string tn = detail::map_template_name< L, std::equal_to, std::allocator > > >(); return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; } }; #endif // array template class L, class T, std::size_t N> struct tn_holder< L > { static std::string type_name( std::string const& suffix ) { std::string tn = detail::array_template_name< L >(); return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_to_string( N ) + '>' + suffix; } }; } // namespace detail template std::string type_name() { return core::detail::tn_holder::type_name( "" ); } } // namespace core } // namespace boost #endif // #ifndef BOOST_CORE_TYPE_NAME_HPP_INCLUDED