From ccdf5ce031df3ad10c36d520e75fe126d0b19166 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 5 Oct 2021 06:45:41 +0300 Subject: [PATCH] Track the type suffix independently for better decomposition of functions and arrays --- include/boost/core/type_name.hpp | 267 ++++++++++++++----------------- test/type_name_test.cpp | 18 +++ 2 files changed, 136 insertions(+), 149 deletions(-) diff --git a/include/boost/core/type_name.hpp b/include/boost/core/type_name.hpp index 8632f81..d31750b 100644 --- a/include/boost/core/type_name.hpp +++ b/include/boost/core/type_name.hpp @@ -244,7 +244,7 @@ inline std::string tn_to_string( std::size_t n ) template int tn_add_each_impl( std::string& st ) { if( !st.empty() ) st += ", "; - st += type_name( tn_identity() ); + st += type_name( tn_identity(), "" ); return 0; }; @@ -262,51 +262,51 @@ template std::string tn_add_each() // primary -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return typeid_name(); + return typeid_name() + suffix; } // cv #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " const"; + return type_name( tn_identity(), " const" + suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " volatile"; + return type_name( tn_identity(), " volatile" + suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " const volatile"; + return type_name( tn_identity(), " const volatile" + suffix ); } #else template typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " const"; + return type_name( tn_identity(), " const" + suffix ); } template typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " volatile"; + return type_name( tn_identity(), " volatile" + suffix ); } template typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + " const volatile"; + return type_name( tn_identity(), " const volatile" + suffix ); } #endif @@ -315,27 +315,27 @@ type_name( tn_identity ) #if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + "&"; + return type_name( tn_identity(), "&" + suffix ); } #else template typename tn_enable_if::value, std::string>::type -type_name( tn_identity ) +type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + "&"; + return type_name( tn_identity(), "&" + suffix ); } #endif #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + "&&"; + return type_name( tn_identity(), "&&" + suffix ); } #endif @@ -344,81 +344,34 @@ template std::string type_name( tn_identity ) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + '(' + tn_add_each() + ')'; + std::string r = type_name( tn_identity(), "" ); + + if( !suffix.empty() ) + { + r += '(' + suffix + ')'; + } + + r += '(' + tn_add_each() + ')'; + + return r; } #endif // pointers -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return type_name( tn_identity() ) + "*"; + return type_name( tn_identity(), "*" + suffix ); } -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -// function references - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(&)(" + tn_add_each() + ')'; -} - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(&&)(" + tn_add_each() + ')'; -} - -#endif - -// function pointers - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(*)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(*&)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(* const)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(* const&)(" + tn_add_each() + ')'; -} - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(*&&)(" + tn_add_each() + ')'; -} - -template std::string type_name( tn_identity ) -{ - return type_name( tn_identity() ) + "(* const&&)(" + tn_add_each() + ')'; -} - -#endif - -#endif - // arrays template std::pair array_prefix_suffix( tn_identity ) { - return std::pair( type_name( tn_identity() ), "" ); + return std::pair( type_name( tn_identity(), "" ), "" ); } template std::pair array_prefix_suffix( tn_identity ) @@ -430,163 +383,179 @@ template std::pair array_prefi return r; } -template std::string array_type_name( tn_identity ) +template std::string array_type_name( tn_identity, std::string const& suffix ) { std::pair r = array_prefix_suffix( tn_identity() ); - return r.first + "[]" + r.second; + + if( suffix.empty() ) + { + return r.first + "[]" + r.second; + } + else + { + return r.first + '(' + suffix + ")[]" + r.second; + } } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string array_type_name( tn_identity ) +template std::string array_type_name( tn_identity, std::string const& suffix ) { std::pair r = array_prefix_suffix( tn_identity() ); - return r.first + r.second; + + if( suffix.empty() ) + { + return r.first + r.second; + } + else + { + return r.first + '(' + suffix + ")" + r.second; + } } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } -template std::string type_name( tn_identity ) +template std::string type_name( tn_identity, std::string const& suffix ) { - return array_type_name( tn_identity() ); + return array_type_name( tn_identity(), suffix ); } // nullptr_t #if !defined(BOOST_NO_CXX11_NULLPTR) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::nullptr_t"; + return "std::nullptr_t" + suffix; } #endif // strings -template class L, class Ch> std::string type_name( tn_identity< L, std::allocator > > ) +template class L, class Ch> std::string type_name( tn_identity< L, std::allocator > >, std::string const& suffix ) { std::string tn = sequence_template_name< L, std::allocator > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::string"; + return "std::string" + suffix; } -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::wstring"; + return "std::wstring" + suffix; } #if !defined(BOOST_NO_CXX11_CHAR16_T) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::u16string"; + return "std::u16string" + suffix; } #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::u32string"; + return "std::u32string" + suffix; } #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L -inline std::string type_name( tn_identity> ) +inline std::string type_name( tn_identity>, std::string const& suffix ) { - return "std::u8string"; + return "std::u8string" + suffix; } #endif // string views (et al) -template class L, class Ch> std::string type_name( tn_identity< L > > ) +template class L, class Ch> std::string type_name( tn_identity< L > >, std::string const& suffix ) { std::string tn = sequence_template_name< L > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } // needed for libstdc++ -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::ostream"; + return "std::ostream" + suffix; } #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::string_view"; + return "std::string_view" + suffix; } -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::wstring_view"; + return "std::wstring_view" + suffix; } #if !defined(BOOST_NO_CXX11_CHAR16_T) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::u16string_view"; + return "std::u16string_view" + suffix; } #endif #if !defined(BOOST_NO_CXX11_CHAR32_T) -inline std::string type_name( tn_identity ) +inline std::string type_name( tn_identity, std::string const& suffix ) { - return "std::u32string_view"; + return "std::u32string_view" + suffix; } #endif #if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L -inline std::string type_name( tn_identity> ) +inline std::string type_name( tn_identity>, std::string const& suffix ) { - return "std::u8string_view"; + return "std::u8string_view" + suffix; } #endif @@ -597,87 +566,87 @@ inline std::string type_name( tn_identity> ) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -template class L, class... T> std::string type_name( tn_identity< L > ) +template class L, class... T> std::string type_name( tn_identity< L >, std::string const& suffix ) { std::string tn = class_template_name< L >(); std::string st = tn_add_each(); - return tn + '<' + st + '>'; + return tn + '<' + st + '>' + suffix; } #else -template class L, class T1> std::string type_name( tn_identity< L > ) +template class L, class T1> std::string type_name( tn_identity< L >, std::string const& suffix ) { std::string tn = class_template_name< L >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } -template class L, class T1, class T2> std::string type_name( tn_identity< L > ) +template class L, class T1, class T2> std::string type_name( tn_identity< L >, std::string const& suffix ) { std::string tn = class_template_name< L >(); - return tn + '<' + type_name( tn_identity() ) + ", " + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + ", " + type_name( tn_identity(), "" ) + '>' + suffix; } #endif // sequence containers -template class L, class T> std::string type_name( tn_identity< L > > ) +template class L, class T> std::string type_name( tn_identity< L > >, std::string const& suffix ) { std::string tn = sequence_template_name< L > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } // set -template class L, class T> std::string type_name( tn_identity< L, std::allocator > > ) +template class L, class T> std::string type_name( tn_identity< L, std::allocator > >, std::string const& suffix ) { std::string tn = set_template_name< L, std::allocator > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } // map -template class L, class T, class U> std::string type_name( tn_identity< L, std::allocator > > > ) +template class L, class T, class U> std::string type_name( tn_identity< L, std::allocator > > >, std::string const& suffix ) { std::string tn = map_template_name< L, std::allocator > > >(); - return tn + '<' + type_name( tn_identity() ) + ", " + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + ", " + type_name( tn_identity(), "" ) + '>' + suffix; } #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) // unordered_set -template class L, class T> std::string type_name( tn_identity< L, std::equal_to, std::allocator > > ) +template class L, class T> std::string type_name( tn_identity< L, std::equal_to, std::allocator > >, std::string const& suffix ) { std::string tn = set_template_name< L, std::equal_to, std::allocator > >(); - return tn + '<' + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + '>' + suffix; } // unordered_map -template class L, class T, class U> std::string type_name( tn_identity< L, std::equal_to, std::allocator > > > ) +template class L, class T, class U> std::string type_name( tn_identity< L, std::equal_to, std::allocator > > >, std::string const& suffix ) { std::string tn = map_template_name< L, std::equal_to, std::allocator > > >(); - return tn + '<' + type_name( tn_identity() ) + ", " + type_name( tn_identity() ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + ", " + type_name( tn_identity(), "" ) + '>' + suffix; } #endif // array -template class L, class T, std::size_t N> std::string type_name( tn_identity< L > ) +template class L, class T, std::size_t N> std::string type_name( tn_identity< L >, std::string const& suffix ) { std::string tn = array_template_name< L >(); - return tn + '<' + type_name( tn_identity() ) + ", " + tn_to_string( N ) + '>'; + return tn + '<' + type_name( tn_identity(), "" ) + ", " + tn_to_string( N ) + '>' + suffix; } } // namespace detail template std::string type_name() { - return core::detail::type_name( core::detail::tn_identity() ); + return core::detail::type_name( core::detail::tn_identity(), "" ); } } // namespace core diff --git a/test/type_name_test.cpp b/test/type_name_test.cpp index b3439c1..ebd3895 100644 --- a/test/type_name_test.cpp +++ b/test/type_name_test.cpp @@ -111,6 +111,12 @@ int main() TEST(int(float, A, B*)); TEST(void(*)()); + TEST(void(**)()); + TEST(void(***)()); + + TEST(void(* const* const*)()); + TEST(void(* const* const&)()); + TEST(void(&)()); #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -125,17 +131,29 @@ int main() TEST(A volatile[]); TEST(A const volatile[]); + TEST(A(&)[]); + TEST(A const(***)[]); + TEST(B[1]); TEST(B const[1]); TEST(B volatile[1]); TEST(B const volatile[1]); + TEST(B(&)[1]); + TEST(B const(***)[1]); + TEST(A[][2][3]); TEST(A const[][2][3]); + TEST(A(&)[][2][3]); + TEST(A const(***)[][2][3]); + TEST(B[1][2][3]); TEST(B const volatile[1][2][3]); + TEST(B(&)[1][2][3]); + TEST(B const volatile(***)[1][2][3]); + #if !defined(BOOST_NO_CXX11_NULLPTR) TEST(std::nullptr_t);