正如许多其他C ++ 0x用户一样,我正在尝试为我的项目创建一个智能指针接口。理想情况下,我喜欢这样的语法,隐藏两种类型和std::make_shared<T>()
调用。
Foo::Ptr foo = Foo::shared();
Foo::UPtr unique_foo = Foo::unique();
我想在结构中放置声明来继承自:
template <class T>
struct SmartDefs
{
typedef std::shared_ptr<T> Ptr;
typedef std::unique_ptr<T> UPtr;
template <class... P>
static Ptr shared(P&&... p)
{
return std::make_shared<T>(std::forward<P>(p)...);
}
template <class... P>
static UPtr unique(P&&... p)
{
return std::unique_ptr<T>(new T(std::forward<P>(p)...));
}
};
现在这本身很好用,但是当继承进入图片时我会遇到问题,因为typedef和shared / unique静态方法定义了两次。我设法使用一些丑陋的宏,私有继承解决这个问题,需要更多的输入,但我想避免这个:
#include <memory>
#include <iostream>
template <class T>
struct SmartDefs
{
typedef std::shared_ptr<T> Ptr;
typedef std::unique_ptr<T> UPtr;
template <class... P>
static Ptr shared(P&&... p)
{
return std::make_shared<T>(std::forward<P>(p)...);
}
template <class... P>
static UPtr unique(P&&... p)
{
return std::unique_ptr<T>(new T(std::forward<P>(p)...));
}
};
#define DECL_SMART(type) using SmartDefs< type >::Ptr; \
using SmartDefs< type >::UPtr; \
using SmartDefs< type >::shared; \
using SmartDefs< type >::unique
class Foo : private SmartDefs<Foo>
{
public:
DECL_SMART(Foo);
virtual void foo() const { std::cout << "Foo" << std::endl; }
};
class Bar : public Foo, private SmartDefs<Bar>
{
public:
DECL_SMART(Bar);
void foo() const { std::cout << "Bar" << std::endl; }
};
template <class T>
struct Baz : private SmartDefs<Baz<T>>
{
DECL_SMART(Baz<T>);
void foo(const T& in) const { std::cout << in << std::endl; }
};
int main()
{
auto foo = Foo::shared();
auto bar = Bar::shared();
auto baz = Baz<int>::shared();
foo->foo();
bar->foo();
baz->foo(10);
foo = bar;
foo->foo();
}
我测试了类似的内容,但它仍然给我shared()
的模糊参考:
template <class T>
struct SmartPtr : private SmartDefs<T>
{
using SmartDefs<T>::Ptr;
using SmartDefs<T>::UPtr;
using SmartDefs<T>::shared;
using SmartDefs<T>::unique;
};
class Foo : public SmartPtr<Foo> {};
答案 0 :(得分:1)
你可以扩展:
现在这本身很好用,但是当继承进入图片时我会遇到问题
您是指从SmartDefs类继承的两个基类的多个继承吗?您是指从SmartDefs类和本身继承自SmartDefs类的基类继承吗?
无论哪种方式,你的问题当然不是C ++ 0x,而是基本成员的一般模糊性。
示例:
#include <iostream>
struct A
{
typedef int ret_type;
static ret_type go(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
struct B
{
typedef int ret_type;
static ret_type go(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
struct C : public A, public B
{
typedef int ret_type;
static ret_type go(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int main()
{
C c;
C::A::ret_type ago = c.A::go();
C::B::ret_type bgo = c.B::go();
C::ret_type cgo = c.go();
C::A::ret_type static_ago = C::A::go();
C::B::ret_type static_bgo = C::B::go();
C::ret_type static_cgo = C::go();
}
因此,您需要以相同的方式解决问题:在调用时明确消除歧义,或者最好重载派生类中的函数/ typedef。
但是,我不确定我会推荐你的解决方案。如果Derived没有从您的SmartPtr类继承,则面向继承Derived::unique()
将返回unique_ptr<Base>
。实现类似这样的东西的唯一“安全”方法是使用虚拟的Create()函数(在您的情况下:CreateUnique,也许是CreateShared)。
我个人更愿意编写一个全局make_shared
来包装std::make_shared
并在同一名称空间中编写我自己的make_unique
。
A::shared() // replace
make_shared<A>() // with this
A::unique() // replace
make_unique<A>() // with this
与不必从SmartDefs继承每个类,并避免使用不当的巨大风险相比,这里的少数字符区别是微不足道的。
编辑:我忘了掩盖你会以这种方式丢失返回类型的typedef。你可以使用type_traits,但我实际上认为缺少typedef是一个功能。 std :: shared_ptr和std :: unique_ptr等核心类的信息不需要进行类型化,在auto
,模板和decltype
之间,几乎不需要显式的typedef。