为什么const模板化引用类型与const引用类型不同?

时间:2011-12-03 18:06:53

标签: c++ templates typedef dynamic-cast

考虑这个模板:

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

    //...

};

我认为const_ref_tanother_const_ref_t类型是等价的。两者都是const T&&#39; s。但事实并非如此。唉,以下关于它们不等价的证明是相当复杂的。它取决于使用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_tfoo< int >::another_const_ref_t视为等效,这对于typedef似乎是合理的。但dynamic_cast<>仅将foo< int >::another_const_ref_t视为等同于const int&。它将在另一个(foo< int >::const_ref_t)情况下返回null。

为什么?

1 个答案:

答案 0 :(得分:6)

考虑一下:

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

现在TRefFoo &相同,TCRefconst Foo &相同。

但是,const TRefconst (TRef) = const (Foo &)相同,而不是(const Foo)&。但引用类型总是不变的,因此额外的const不会添加任何内容。

如果您更喜欢与指针进行比较:T&基本上类似于T * const,那么TRef const就像(T * const) const一样,只会折叠为T * const。< / p>