Почему шаблонный ссылочный тип const отличается от ссылочного типа const? - PullRequest
4 голосов
/ 03 декабря 2011

Рассмотрим этот шаблон:

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) случае он вернет ноль.

Почему?

1 Ответ

6 голосов
/ 03 декабря 2011

Учтите это:

typedef Foo T;
typedef T & TRef;
typedef T const & TCRef;

Теперь TRef совпадает с Foo &, а TCRef совпадает с const Foo &.

Однако const TRefсовпадает с const (TRef) = const (Foo &), а не (const Foo)&.Но ссылочные типы всегда постоянны, поэтому дополнительный const ничего не добавляет.

Если вы предпочитаете сравнение с указателями: T& по существу похож на T * const, поэтому TRef const похож на (T * const) const, который просто падает до T * const.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...