Dav*_*vid 8 c++ visual-studio-2010
以下代码输出:
struct Property<int>::IValue
但我希望它输出:
struct Property<int>::Value<int>
码:
struct IProperty
{
virtual ~IProperty() = 0;
};
IProperty::~IProperty(){}
template<typename T>
struct Property : IProperty
{
struct IValue
{
virtual ~IValue() = 0;
};
template<typename Q>
struct Value : IValue
{
Q thing;
};
Property() : m_pValue(new Value<T>()){}
std::shared_ptr<IValue> m_pValue;
};
template<typename T>
Property<T>::IValue::~IValue(){}
int main()
{
std::unique_ptr<IProperty> p(new Property<int>);
std::cout << typeid(*static_cast<Property<int>&>(*p).m_pValue).name() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
如果IValue并且Value被移到外面Property以便它们不再是嵌套类,我得到了我期望的结果.这是VS Bug还是预期的行为?
这绝对是 Visual C++ 编译器错误。由于某些奇怪的原因,编译器无法确定Property<T>::IValue从shared_ptr多态基类取消引用,并使用静态类型信息作为typeid表达式而不是运行时类型信息。
重现该错误的最少代码:
template <class T> struct Property
{
struct IValue
{
void f() {}
virtual ~IValue() = 0 {}
};
struct Value: IValue {};
Property(): m_pValue(new Value())
{
// typeid inside class works as expected
std::cout << "Inside class: " << typeid(*m_pValue).name() << std::endl;
}
// If changed to unique_ptr typeid will work as expected
// But if changed to raw pointer the bug remains!
std::shared_ptr<IValue> m_pValue;
};
int main()
{
Property<int> p;
// If next line uncommented typeid will work as expected
//p.m_pValue->f();
std::cout << "Outside class: " << typeid(*p.m_pValue).name() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我玩了一下这个示例,发现它typeid开始按预期工作,并且如果之前调用了指向对象的某些函数typeid或者shared_ptr将其替换为unique_ptr. 有趣,但替换shared_ptr<IValue>为IValue*仍然会重现该错误!
实际输出:
类内部:struct Property<int>::Value 类外:struct Property<int>::IValue
预期(正确)输出:
类内部:struct Property<int>::Value 类外:struct Property<int>::Value
从汇编程序列表可以清楚地看出,这确实是编译器问题:
typeid从Propertyctor 调用会生成对 的诚实调用__RTtypeid:
; 225 : std::cout << typeid(*m_pValue).name() << std::endl;
... irrelevant code skipped ...
; __type_info_root_node
push OFFSET ?__type_info_root_node@@3U__type_info_node@@A
mov ecx, DWORD PTR _this$[ebp]
; std::tr1::shared_ptr<Property<int>::IValue>::operator*
call ??D?$shared_ptr@UIValue@?...<skipped>
push eax
call ___RTtypeid
Run Code Online (Sandbox Code Playgroud)
typeid外部调用生成静态IValue类型信息:
; 237 : std::cout << typeid(*p.m_pValue).name() << std::endl;
... irrelevant code skipped ...
; __type_info_root_node
push OFFSET ?__type_info_root_node@@3U__type_info_node@@A
mov ecx, OFFSET ??_R0?AUIValue@?$Property@H@@@8
Run Code Online (Sandbox Code Playgroud)
另请注意,VS2008 中也存在相同的错误,因此这是旧时的行为。
| 归档时间: |
|
| 查看次数: |
251 次 |
| 最近记录: |