【问题标题】:Is it possible to pass a vector<shared_ptr<T>> to a const vector<shared_ptr<const T>>& parameter?是否可以将 vector<shared_ptr<T>> 传递给 const vector<shared_ptr<const T>>& 参数?
【发布时间】:2017-07-18 12:01:39
【问题描述】:

假设我们有以下函数:

void doStuff(const std::vector<std::shared_ptr<const Foo>>& fs) { }

有没有办法(安全地)将std::vector&lt;std::shared_ptr&lt;Foo&gt;&gt; 传递给这个参数?例如:

std::vector<std::shared_ptr<Foo>> foos;
doStuff(foos);

这种隐式转换失败了,但可以通过强制转换安全地完成吗? (这在理论上似乎是安全的,因为doStuff 函数将无法修改向量,也无法修改其中的对象。)

【问题讨论】:

  • 我发现将 shared_ptr 设为 const 项会增加不必要的复杂性。但我认为没有 hack 就无法做到这一点。
  • 这绝对是未定义的行为。内存布局可能看起来它应该每次都可以工作,但你不能依赖它。谁知道编译器可能会进行什么转换,包括删除任何呈现未定义行为的代码。
  • 什么是未定义行为?我的问题中的代码无法编译,所以也许您指的是一些假设的const_cast
  • @jtbandes 道歉,我指的是假设的 reinterpret_cast 或 c 演员。我看不出const_cast 是如何解决这个问题的。如果它只是一个const_cast 它可以很好地定义。 const_cast 无法从 std::vector&lt;const T&gt;&amp; 转换为 std::vector&lt;T&gt;&amp;
  • @AnonMail 我知道它是如何增加复杂性的,但是在这里省略const 也会允许被调用者修改底层对象。有没有办法避免这种情况?我想如果shared_ptr 只有T* operator-&gt;();const T* operator-&gt;() const; 那么它可以与const vector&lt;shared_ptr&lt;T&gt;&gt; 一起工作,但事实并非如此......

标签: c++ type-conversion constants shared-ptr


【解决方案1】:

没有。但是您可以做的是将界面更改为更具包容性。你写:

void doStuff(std::vector<std::shared_ptr<Foo const>> const& fs) { }

但你真正想要的只是std::shared_ptr&lt;const Foo&gt; 的一些连续范围,对吗?因此,让我们将其更改为:

void doStuff(gsl::span<std::shared_ptr<Foo const>> fs) { }

但实际上,我们是否需要共享指针本身指向const 或者它们是const 就足够了?

void doStuff(gsl::span<std::shared_ptr<Foo> const> fs) { }

现在我们有了一个可以用std::vector&lt;shared_ptr&lt;Foo&gt;&gt; 调用的接口。

【讨论】:

    【解决方案2】:

    简短的回答是“不”。

    给定一个类模板

    template <typename T> struct Foo {};
    

    Foo&lt;int&gt;Foo&lt;const int&gt; 是两种不同的类型。两种类型之间没有隐式转换。

    我的建议是将doStuff 设为函数模板。

    template <typename T>
    void doStuff(const std::vector<T>& fs) { }
    

    template <typename T>
    void doStuff(const std::vector<std::shared_ptr<T>>& fs) { }
    

    如果您没有修改doStuff 的选项,那么将doStuff 中的代码复制为shared_ptr&lt;Foo&gt; 可能是唯一明智的做法。

    【讨论】:

    • 我知道隐式转换不起作用,但我想问是否有某种方法可以在这里安全地使用显式转换。
    • 作为一种解决方法,可能值得研究 std::transform(en.cppreference.com/w/cpp/algorithm/transform) 并将 doSomething 更改为一次获取​​一个项目并将其转换为正确的类型。
    猜你喜欢
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多