考虑这个模板:
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&
&#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_t
和foo< int >::another_const_ref_t
视为等效,这对于typedef似乎是合理的。但dynamic_cast<>
仅将foo< int >::another_const_ref_t
视为等同于const int&
。它将在另一个(foo< int >::const_ref_t
)情况下返回null。
为什么?
答案 0 :(得分:6)
考虑一下:
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
。< / p>