mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Fixed type name extraction involving template classes
git-svn-id: https://svn.code.sf.net/p/turtle/code/trunk@585 860be788-9bd5-4423-9f1e-828f051e677b
This commit is contained in:
parent
b21790be27
commit
4cd3d08e3e
3 changed files with 152 additions and 25 deletions
|
|
@ -11,6 +11,7 @@ Not yet released
|
||||||
* Fixed potential conflict with macro max
|
* Fixed potential conflict with macro max
|
||||||
* Fixed missing file name and line number in logs
|
* Fixed missing file name and line number in logs
|
||||||
* Moved mock::exception in its own header so that it can be included without the error policy
|
* Moved mock::exception in its own header so that it can be included without the error policy
|
||||||
|
* Fixed type name extraction involving template classes
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,21 +19,57 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct my_type_from_default_namespace {};
|
BOOST_AUTO_TEST_CASE( name_of_base_type_is_extracted )
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( name_of_type_from_default_namespace_is_extracted )
|
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL( "my_type_from_default_namespace", to_string( my_type_from_default_namespace() ) );
|
BOOST_CHECK_EQUAL( "char", to_string( 'a' ) );
|
||||||
|
BOOST_CHECK_EQUAL( "bool", to_string( true ) );
|
||||||
|
BOOST_CHECK_EQUAL( "int", to_string< int >( 0 ) );
|
||||||
|
BOOST_CHECK_EQUAL( "short", to_string< short >( 0 ) );
|
||||||
|
BOOST_CHECK_EQUAL( "long", to_string< long >( 0 ) );
|
||||||
|
BOOST_CHECK_EQUAL( "unsigned int", to_string< unsigned int >( 0 ) );
|
||||||
|
BOOST_CHECK_EQUAL( "unsigned short", to_string< unsigned short >( 0 ) );
|
||||||
|
BOOST_CHECK_EQUAL( "unsigned long", to_string< unsigned long >( 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct my_type_in_default_namespace
|
||||||
|
{
|
||||||
|
struct inner {};
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( name_of_type_in_default_namespace_is_extracted )
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL( "my_type_in_default_namespace", to_string( my_type_in_default_namespace() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( name_of_inner_type_from_type_in_default_namespace_is_extracted )
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL( "inner", to_string( my_type_in_default_namespace::inner() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
struct my_template_type_in_default_namespace
|
||||||
|
{
|
||||||
|
struct inner {};
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( name_of_template_type_in_default_namespace_is_extracted )
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL( "my_template_type_in_default_namespace<int>", to_string( my_template_type_in_default_namespace<int>() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( name_of_inner_type_from_template_type_in_default_namespace_is_extracted )
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL( "inner", to_string( my_template_type_in_default_namespace<int>::inner() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
struct my_type_from_anonymous_namespace {};
|
struct my_type_in_anonymous_namespace {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( name_of_type_from_anonymous_namespace_is_extracted )
|
BOOST_AUTO_TEST_CASE( name_of_type_in_anonymous_namespace_is_extracted )
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL( "my_type_from_anonymous_namespace", to_string( my_type_from_anonymous_namespace() ) );
|
BOOST_CHECK_EQUAL( "my_type_in_anonymous_namespace", to_string( my_type_in_anonymous_namespace() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace nm
|
namespace nm
|
||||||
|
|
@ -50,26 +86,26 @@ namespace nm
|
||||||
{
|
{
|
||||||
namespace inner
|
namespace inner
|
||||||
{
|
{
|
||||||
struct my_type_from_named_inner_namespace {};
|
struct my_type_in_named_inner_namespace {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( name_of_type_from_named_inner_namespace_is_extracted )
|
BOOST_AUTO_TEST_CASE( name_of_type_in_named_inner_namespace_is_extracted )
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL( "my_type_from_named_inner_namespace", to_string( nm::inner::my_type_from_named_inner_namespace() ) );
|
BOOST_CHECK_EQUAL( "my_type_in_named_inner_namespace", to_string( nm::inner::my_type_in_named_inner_namespace() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
namespace inner
|
namespace inner
|
||||||
{
|
{
|
||||||
struct my_type_from_unnamed_inner_namespace {};
|
struct my_type_in_unnamed_inner_namespace {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( name_of_type_from_unnamed_inner_namespace_is_extracted )
|
BOOST_AUTO_TEST_CASE( name_of_type_in_unnamed_inner_namespace_is_extracted )
|
||||||
{
|
{
|
||||||
BOOST_CHECK_EQUAL( "my_type_from_unnamed_inner_namespace", to_string( inner::my_type_from_unnamed_inner_namespace() ) );
|
BOOST_CHECK_EQUAL( "my_type_in_unnamed_inner_namespace", to_string( inner::my_type_in_unnamed_inner_namespace() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( name_of_local_type_is_extracted )
|
BOOST_AUTO_TEST_CASE( name_of_local_type_is_extracted )
|
||||||
|
|
@ -77,3 +113,61 @@ BOOST_AUTO_TEST_CASE( name_of_local_type_is_extracted )
|
||||||
struct my_local_type {};
|
struct my_local_type {};
|
||||||
BOOST_CHECK_EQUAL( "my_local_type", boost::lexical_cast< std::string >( mock::detail::type_name( BOOST_SP_TYPEID( my_local_type ) ) ) );
|
BOOST_CHECK_EQUAL( "my_local_type", boost::lexical_cast< std::string >( mock::detail::type_name( BOOST_SP_TYPEID( my_local_type ) ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template< typename T >
|
||||||
|
struct my_template_type
|
||||||
|
{
|
||||||
|
struct inner {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( name_of_template_type_in_anonymous_namespace_is_extracted )
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL( "my_template_type<int>", to_string( my_template_type< int >() ) );
|
||||||
|
BOOST_CHECK_EQUAL( "my_template_type<exception>", to_string( my_template_type< std::exception >() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( name_of_inner_type_from_template_type_in_anonymous_namespace_is_extracted )
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL( "inner", to_string( my_template_type< int >::inner() ) );
|
||||||
|
BOOST_CHECK_EQUAL( "inner", to_string( my_template_type< std::exception >::inner() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace nm
|
||||||
|
{
|
||||||
|
template< typename T >
|
||||||
|
struct my_template_type
|
||||||
|
{
|
||||||
|
struct inner {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( name_of_template_type_in_named_namespace_is_extracted )
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL( "my_template_type<int>", to_string( nm::my_template_type< int >() ) );
|
||||||
|
BOOST_CHECK_EQUAL( "my_template_type<exception>", to_string( nm::my_template_type< std::exception >() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( name_of_inner_type_from_template_type_in_named_namespace_is_extracted )
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL( "inner", to_string( nm::my_template_type< int >::inner() ) );
|
||||||
|
BOOST_CHECK_EQUAL( "inner", to_string( nm::my_template_type< std::exception >::inner() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace nm2
|
||||||
|
{
|
||||||
|
template< typename T >
|
||||||
|
struct my_template_type
|
||||||
|
{
|
||||||
|
template< typename U >
|
||||||
|
struct inner {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( name_of_inner_type_from_template_type_in_named_namespace_is_extracted2 )
|
||||||
|
{
|
||||||
|
BOOST_CHECK_EQUAL( "inner<int>", to_string( nm2::my_template_type< int >::inner< int >() ) );
|
||||||
|
BOOST_CHECK_EQUAL( "inner<int>", to_string( nm2::my_template_type< std::exception >::inner< int >() ) );
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,16 @@ namespace detail
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
typedef boost::unit_test::const_string const_string;
|
||||||
|
typedef const_string::size_type size_type;
|
||||||
|
|
||||||
void serialize( std::ostream& s,
|
void serialize( std::ostream& s,
|
||||||
const boost::detail::sp_typeinfo& info ) const
|
const boost::detail::sp_typeinfo& info ) const
|
||||||
{
|
{
|
||||||
const char* name = info.name();
|
const char* name = info.name();
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
int status = 0;
|
int status = 0;
|
||||||
char* result = abi::__cxa_demangle( name, NULL, 0, &status );
|
char* result = abi::__cxa_demangle( name, 0, 0, &status );
|
||||||
struct guard
|
struct guard
|
||||||
{
|
{
|
||||||
explicit guard( char* p )
|
explicit guard( char* p )
|
||||||
|
|
@ -49,7 +52,7 @@ namespace detail
|
||||||
{}
|
{}
|
||||||
~guard()
|
~guard()
|
||||||
{
|
{
|
||||||
free( p_ );
|
std::free( p_ );
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
char* p_;
|
char* p_;
|
||||||
|
|
@ -60,22 +63,51 @@ namespace detail
|
||||||
#endif
|
#endif
|
||||||
serialize( s, name );
|
serialize( s, name );
|
||||||
}
|
}
|
||||||
void serialize( std::ostream& s,
|
void serialize( std::ostream& s, const_string name ) const
|
||||||
boost::unit_test::const_string name ) const
|
|
||||||
{
|
{
|
||||||
boost::unit_test::const_string::size_type p = name.rfind( "::" );
|
const size_type tpl_end = name.rfind( ">" );
|
||||||
if( p != boost::unit_test::const_string::npos )
|
const size_type nm = name.rfind( "::" );
|
||||||
|
if( tpl_end == const_string::npos || tpl_end <= nm )
|
||||||
{
|
{
|
||||||
s << name.substr( p + 2 );
|
s << remove_prefix( remove_namespace( name ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p = name.rfind( " " );
|
const size_type tpl_start = find_template_start( name );
|
||||||
if( p != boost::unit_test::const_string::npos )
|
s << remove_namespace( name.substr( 0, tpl_start ) ) << '<';
|
||||||
{
|
serialize( s, name.substr( tpl_start + 1, tpl_end ) );
|
||||||
s << name.substr( p + 1 );
|
s << '>';
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
s << name;
|
const_string remove_prefix( const_string name ) const
|
||||||
|
{
|
||||||
|
name = remove_prefix( name, "class " );
|
||||||
|
name = remove_prefix( name, "struct " );
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
const_string remove_prefix( const_string name,
|
||||||
|
const_string prefix ) const
|
||||||
|
{
|
||||||
|
if( name.substr( 0, prefix.size() ) == prefix )
|
||||||
|
return name.substr( prefix.size() );
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
size_type find_template_start( const_string name ) const
|
||||||
|
{
|
||||||
|
size_type count = 0;
|
||||||
|
for( size_type i = name.size(); i > 0; --i )
|
||||||
|
{
|
||||||
|
if( name[ i ] == '>' )
|
||||||
|
++count;
|
||||||
|
if( name[ i ] == '<' && --count == 0 )
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return static_cast< size_type >( const_string::npos );
|
||||||
|
}
|
||||||
|
const_string remove_namespace( const_string name ) const
|
||||||
|
{
|
||||||
|
size_type p = name.rfind( "::" );
|
||||||
|
if( p == const_string::npos )
|
||||||
|
return name;
|
||||||
|
return name.substr( p + 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
const boost::detail::sp_typeinfo* info_;
|
const boost::detail::sp_typeinfo* info_;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue