将对具有shared_ptr作为值的映射的引用转换为对具有shared_ptr和const作为值的映射的引用

时间:2019-06-02 15:13:28

标签: c++

假设我们有一个像这样的成员类 std::map<unsigned int, std::shared_ptr<ObscureType>> member_ 我们不能用具有member的映射替换std::shared_ptr<const ObscureType>,因为该类必须对ObscureType的非常量函数进行操作。

该类现在应该具有一个函数const std::map<unsigned int, std::shared_ptr<const ObscureType>& getUnderlyingMap() const。 其他类可能将此类作为依赖项,并且必须在ObscureType的const函数上进行操作。

我们不能简单地写 return member_中的getUnderlyingMap(),因为不允许这种隐式转换。

由于static_castconst_cast不起作用,我选择了reinterpret_cast

因此方法主体为

const std::map<unsigned int, std::shared_ptr<const ObscureType>& getUnderlyingMap() const {
    return reinterpret_cast<const std::map<unsigned int, std::shared_ptr<const ObscureType>&>(member_);
}

在这种情况下使用reinterpret_cast是否安全?

有没有更好的方法来解决此问题?请注意,由于创建对象的方式(Node-V8集成),不选择不使用shared_ptr

2 个答案:

答案 0 :(得分:3)

不,那根本不安全。

我可以想到两个选择:不用公开地图,而是公开所需的功能(较少出错,而且不太干净,并且不能使用要求std::map的接口):

std::shared_ptr<const ObscureType> getInUnderlyingMap(unsigned int index) const {
    return member_.at(index);  // Might want to return nullptr instead of throwing
}
std::size_t sizeOfUnderlyingMap() const noexcept {
    return member_.size();
}
// etc.

或者您可以将member_设为std::map<unsigned int, std::shared_ptr<const ObscureType>>,在getUnderlyingMap中通过const引用将其返回,并在内部使用std::const_pointer_cast在不使用const的情况下使用它(请确保您尽管正在分配非常量指针,所以const_pointer_cast不是UB):

private:
std::map<unsigned int, std::shared_ptr<const ObscureType>> member_;

std::shared_ptr<ObscureType> obscure_object(const std::shared_ptr<const ObscureType>& p) noexcept {
    return std::const_pointer_cast<ObscureType>(p);
}
std::shared_ptr<ObscureType> obscure_object(std::shared_ptr<const ObscureType>&& p) noexcept {
    return std::const_pointer_cast<ObscureType>(std::move(p));
}

void internal_method() {
    obscure_object(member_[0]).non_const_method();
}

public:
const std::map<unsigned int, std::shared_ptr<const ObscureType>& getUnderlyingMap() const {
    return member_;
}

答案 1 :(得分:0)

重新解释类型转换与以往一样不安全且已实现定义,您可以使用C样式的类型转换,该类型至少会向偶然的观察者伸出。由于 $( 'a[href^="#"]' ).on( 'click', function ( event ) { var target = $( $( this ).attr( 'href' ) ); var znacznik = $( $( this ).attr( 'a' ) ); if ( target.length ) { event.preventDefault(); $( 'html, body' ).animate( { scrollTop: target.offset().top - 80 }, 1000 ); } } ); map<key, value*>不太可能具有不同的二进制布局,因此剩下的只是用于编译时机制的类型安全检查,因此这应该在实践中起作用。

尽管要当心:

map<key, value const*>

尽管您的示例正确无误,但您一次将const添加到两个级别上可以避免进行修改。