0

我想将对象的(共享)所有权传递给函数foo::bar。问题是我不在乎,所有权是独占的还是共享的。我认为class foo这是一个我不想关心所有权细节的界面。我所关心的是,我可以确保传递的智能指针的生命周期超出foo::bar.

现在我可以写了

class foo {
  void bar( std::shared_ptr<blub> );
  void bar( std::unique_ptr<blub> );
};

但这在我们积累了几个智能指针变体的时候是不优雅的。为每个变体编写重载非常麻烦,特别是如果我想在我的代码中多次使用这个方案。

现在我也不想foo被模板化,因为模板很复杂。

我能想到的最简单的是智能指针包装器

template <typename T>
class owning_ptr {
  // Sorts out the largest type so we can allocate enough space
  typedef largest<std::shared_ptr<T>, std::unique_ptr<T>, myptr<T>>::type big_type;
  typedef std::aligned_storage <sizeof(big_type), std::alignment_of<big_type>::value>::type buffer_type;
  buffer_type _internal;
  int _type;
};

这有点低效。有没有更好的方法来构造包装器?

最后,我真的很想得到签名:

class foo {
  void bar( owning_ptr<blub> );
};
4

1 回答 1

0

注意:底部有一个有趣的 EDIT

如果您不想对拥有的指针类型进行参数化或重载,则最好采用 ashared_ptr<>并强制转换unique_ptr<>. 我能想到的任何非模板解决方案都至少具有与 a 相同的开销shared_ptr,大多数需要多态调用、自由存储分配或两者兼而有之。

您可能能够shared_ptr通过采用某种类型的代理转换器来自动转换,这应该允许您采用unique_ptrR 值或 ashared_ptr而无需强制转换或显式转换(除了move())并提取可用shared_ptr以存储在您的实例中。这是一个例子:

#include <iostream>
#include <memory>
#include <utility>
using namespace std;

// Take an instance of gimme_owned_ptr<T> to save off a shared_ptr<T>
// from either a shared_ptr or unique_ptr.
template<typename T>
struct gimme_owned_ptr {
    // Make the two constructors templates so we can accept
    // any convertible owning pointer:
    template<typename S>
    gimme_owned_ptr( unique_ptr<S> p )
        : p_( shared_ptr<S>( move(p) ) )
    { }
    template<typename S>
    gimme_owned_ptr( shared_ptr<S> p )
        : p_( p )
    { }
    shared_ptr<T> get() const {
        return p_;
    }
private:
    shared_ptr<T> p_;
};

struct Foo {
    void operator()() const { v_call(); }
    virtual ~Foo() { }
private:
    virtual void v_call() const = 0;
};

struct Bar {
    Bar( gimme_owned_ptr<Foo const> const &gop )
        : foo_( gop.get() )
    { }
    void operator()() const { (*foo_)(); }
private:
    shared_ptr<Foo const> foo_;
};

struct Baz : Foo {
private:
    virtual void v_call() const { cout << "Baz()()\n"; }
};

int main() {
    unique_ptr<Baz> upf( new Baz() );
    shared_ptr<Baz> spf( new Baz() );

    Bar upb( move( upf ) );
    Bar spb( spf );

    upb();
    spb();
}

是的,此解决方案确实使用模板,但仅用于gimme_owned_ptr实用程序类模板,并且仅用于重用和转换。您自己的类(Bar在这种情况下)不需要是模板,也不需要重新实现gimme_owned_ptr以将其与另一种类型一起使用。

======== 编辑 ========

unique_ptr我刚刚检查过,从to的内置转换shared_ptr基本上完成了gimme_owned_ptr我上面写的所有类。如果该类采用 类型shared_ptr<T>,则传递 amove(unique_ptr<S>)将导致可行的转换。因此,您真正需要的只是获取 a shared_ptr,而用户唯一要做的就是调用move()s unique_ptr(无论如何他们都应该这样做)。使用 like 的唯一原因gimme_owned_ptr是接受不同的指针混合或以不同的方式接受它们。(例如,您可以通过在内部调用move()a 来避免不必要的事情,但这可能是个坏主意,因为它会默默地夺取所有权。)unique_ptr<S>&move()

于 2013-05-28T22:45:31.630 回答