سؤال

Consider this template:

template< typename T, typename RefT = T& >
class foo
{
    typedef const RefT const_ref_t;
    typedef const T&   another_const_ref_t;

    //...

};

I would assume that the types const_ref_t and another_const_ref_t would be equivalent. Both are const T&'s. Yet they are not. Alas, the following demonstration of their not-equivalence is fairly elaborate. It hinges on using dynamic_cast<> to check the type of of another class.

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.
}

Sorry this is so complex, but it's a simplified version of the situation where I discovered the question.

The question, then, is this. This code treats const int&, foo< int >::const_ref_t, and foo< int >::another_const_ref_t as equivalent, which seems reasonable given the typedefs. Yet dynamic_cast<> only treats foo< int >::another_const_ref_t as equivalent to const int&. It will return null in the other (foo< int >::const_ref_t) case.

Why?

هل كانت مفيدة؟

المحلول

Consider this:

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

Now TRef is the same as Foo &, and TCRef is the same as const Foo &.

However, const TRef is the same as const (TRef) = const (Foo &), not (const Foo)&. But reference types are always constant, so the additional const doesn't add anything.

If you prefer the comparison with pointers: T& is essentially like T * const, so TRef const is like (T * const) const, which just collapses to T * const.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top