Рассмотрим этот шаблон:
template< typename T, typename RefT = T& >
class foo
{
typedef const RefT const_ref_t;
typedef const T& another_const_ref_t;
//...
};
Я бы предположил, что типы const_ref_t
и another_const_ref_t
будут эквивалентны.Оба const T&
.Все же они не.Увы, следующая демонстрация их неэквивалентности довольно сложна.Он использует dynamic_cast<>
для проверки типа другого класса.
class abstractBase
{
public: virtual ~abstractBase() {}
};
template< typename T >
class otherClass : public abstractBase
{
};
template< typename T, typename RefT = T& >
class foo
{
typedef const RefT const_ref_t;
typedef const T& another_const_ref_t;
public:
void discover( abstractBase* p )
{
otherClass< const_ref_t >* a =
dynamic_cast< otherClass< const_ref_t >* >( p );
otherClass< another_const_ref_t >* b =
dynamic_cast< otherClass< another_const_ref_t >* >( p );
assert( a ); // Fails
assert( b ); // Succeeds
}
};
void fn()
{
abstractBase* p = new otherClass< const int& >();
foo< int > f;
f.discover( p ); // Assertion on 'a' fails.
}
Извините, это так сложно, но это упрощенная версия ситуации, когда я обнаружил вопрос.
Вопрос в следующем.Этот код обрабатывает const int&
, foo< int >::const_ref_t
и foo< int >::another_const_ref_t
как эквивалентные, что представляется разумным, учитывая typedefs.И все же dynamic_cast<>
рассматривает только foo< int >::another_const_ref_t
как эквивалент const int&
.В другом (foo< int >::const_ref_t
) случае он вернет ноль.
Почему?