shared_ptr没有RTTI?

Phi*_*ipp 7 c++ gcc stl mplab c++11

我试图shared_ptr在一个嵌入式项目中使用,该项目是用xc32 1.34(gcc 4.5.2的衍生物)构建的.该项目已禁用RTTI -fno-rtti.

#include <memory>
Run Code Online (Sandbox Code Playgroud)

只是包含标题给我以下错误:

/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory: In member function 'virtual void* std::tr1::_Ref_count_del<_Ty, _Dx>::_Get_deleter(const std::type_info&) const':
In file included from APP/MODULES/LIGHT_MANAGER/LightManager.cpp:13:0:
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory:1264:39: error: cannot use typeid with -fno-rtti
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory: In member function 'virtual void* std::tr1::_Ref_count_del_alloc<_Ty, _Dx, _Alloc>::_Get_deleter(const std::type_info&) const':
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory:1299:39: error: cannot use typeid with -fno-rtti
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory: In function '_Dx* std::tr1::get_deleter(const std::tr1::shared_ptr<_Ty2>&)':
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory:1956:44: error: cannot use typeid with -fno-rtti
Run Code Online (Sandbox Code Playgroud)

所以我想知道的是:shared_ptr没有RTTI 通常不可能使用,或者我做错了什么?

eca*_*mur 8

问题是get_deleter免费功能:

template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;
Run Code Online (Sandbox Code Playgroud)

返回:如果p拥有d类型为cv -unqualified 的删除器D,则返回std:addressof(d); 否则返回nullptr.只要存在shared_ptr拥有的实例,返回的指针就会保持有效d.

显然,最直接的实现是typeid将删除器存储在控制块中.虽然还有其他可能的实现,但它们会(a)更复杂,(b)失去与启用RTTI的代码的二进制兼容性,以及(c)违背"精神" -fno-rtti.

另一个有问题的功能是dynamic_pointer_cast调用dynamic_cast存储的指针.

但是,主要功能shared_ptr是在不使用RTTI功能的情况下实现的,事实上正如Sergei Nikulov上面提到的那样,除了和函数之外,shared_ptrgcc 4.8.5附带-fno-rtti的功能也可以使用; 只要您不使用这些设施,就没有理由不能使用.这可以与例如在没有使用时不可实现的情况形成对比.get_deleterdynamic_pointer_castshared_ptranytypeid

供应商有责任提供适用于其编译器的所有配置的标准库,包括支持其使用的非标准库.但是,如果您的供应商不合作,您仍有几个选择:

  • 修补提供的标准库以删除损坏的get_deleter代码;
  • 使用替代标准库(例如,最新的libstdc ++或libc ++);
  • 使用替代智能指针工具(例如Boost)或自己编写一个.