高效地在 vector<shared_ptr<T>> 和 vector<shared_ptr<const T>> 之间进行转换

4

我有一个类:

class X {
  vector<shared_ptr<T>> v_;

 public:
  vector<shared_ptr<const T>> getTs() { return v_; }
};

它有一个类型为Tshared_ptr类型的向量。由于某种原因,它需要公开一种方法来返回该向量。然而,我不希望修改向量内容,也不希望被指向的对象被修改。所以我需要返回一个vector类型的shared_ptr<const T>向量。
我的问题是,是否有有效的方法实现这个目标?如果我直接返回它,它可以工作,但它需要重构一个向量,这有点贵。
谢谢。

6
它实际上贵了吗?你有进行过测量吗? - Kerrek SB
一个非复制转换本质上不是非const安全的吗?想象一下,如果类的客户端调用了getTs().push_back(shared_ptr_to_truly_const_object);那么你的类可以通过v_修改truly_const_object。(这也是为什么没有从T **const T **的隐式转换的原因。) - ruakh
1
@icando:这并不意味着它实际上是你代码中的瓶颈。;-] - ildjarn
@ruakh:关键是,在这里,vector<T> const&将无法达到目的,因为他有一个vector<shared_ptr<T>>并且想要返回一个vector<shared_ptr<T const>>。我总体上同意你的观点,但在这种情况下,这根本不是一个选项。 - ildjarn
@ruakh:我也留了一条评论而不是答案。我认为在评论中没有必要那么详细。;-] - ildjarn
显示剩余5条评论
3个回答

4
你不能直接这样做 - 但你可以在你的容器上定义“视图”,如果你想确保你的指针是const,那么你可以做非常相似的事情:
boost::any_range<
  std::shared_ptr<const int>,
  boost::random_access_traversal_tag,
  std::shared_ptr<const int>,
  std::ptrdiff_t
> foo(std::vector<std::shared_ptr<int>>& v)
{
  return v;
}

一个简单的转换迭代器适配器/转换范围也可以起到作用,我只是用它来说明这一点。


KitsuneYMG的回答和这个都符合我的需求。 - Kan Li
1
请注意,如果您使用此方法,由于底层容器是 std::vector<>,因此您可以使用 boost::random_access_traversal_tag 来允许对视图进行随机访问遍历,而不仅限于前向遍历。 - ildjarn
又是 Boost 的另一个部分,我需要去调查一下。我真希望我们在工作开发中的手不被 C89 绑住。诅咒你,Mathworks! - KitsuneYMG

2
为什么不将它作为一组 iterator 返回?
class X {
  vector<shared_ptr<T>> v_;
  class const_iterator : std::iterator< std::bidirectional_iterator_tag, T >
  {
    vector<shared_ptr<T>>::iterator it;
    const_iterator( vector<shared_ptr<T>>::iterator& v ) :it (v) { }
    const T& operator*() { return const_cast<const T>( **it ); }
    //forward all methods
  }

   public:
  const_iterator ts_begin() { return const_iterator(v_.begin()); }
  const_iterator ts_end() { return const_iterator(v_.end()); }
};

或者类似的东西?这可以让您完全控制类型以及如何访问它。此外,您可以稍后更改类型而不更改API。

1

你正在按值返回,因此无论您返回原始向量的副本、向量的副本还是shared_ptr<T const> 的向量的副本,成本都相同: 一个内存分配和 N 个原子增量(约)。

如果您想避免创建返回的向量(即通过值返回),那么这是不可能的,因为不同的模板实例化是不相关的类型,无论模板参数有多相关。


也许我没有表达清楚问题,抱歉我的英语不好。我试图实现类似于 const vector<shared_ptr<const T>>& getTs() { return v_; } 的东西。然而,这样做行不通,因为C++认为 shared_ptr<const T> 和 shared_ptr<T> 不是相同的类型。 - Kan Li
回复:第一段:我相信原帖作者已经理解了这一点。因此他/她说:“如果我只是返回它,它可以工作,但需要重构一个向量,这有点昂贵。”(我假设他/她所说的“只是返回它”是指“按值返回它”。) - ruakh
@icando:是的,那是第二段... shared_ptr<T>shared_ptr<T const> 是完全不相关的类型,所以这是不可能的。 - David Rodríguez - dribeas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接