2011-02-26 55 views
0

与许多其他C++ 0x用户一样,我试图为我的项目制作智能指针接口。理想情况下,我喜欢这样的语法,隐藏这两种类型和std::make_shared<T>()调用。如何声明静态函数和typedefs public,它不能被继承?

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和共享/唯一静态方法被定义两次。我设法解决此问题,使用一些丑陋的宏,私有继承,需要更多的打字,但我想避免这种情况:

#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> {}; 

回答

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(); 
} 

所以,你需要解决的问题是相同的:明确歧义在通话时间,或者,最好在你的派生类重载函数/类型定义。

但是,我不确定我会推荐你​​的解决方案。如果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继承每个类,并避免使用不当造成的很大的风险。

编辑:我忘了说你会失去这种返回类型的typedefs。你可以使用type_traits,但我实际上认为这里没有typedef一个特性。核心类如std :: shared_ptr和std :: unique_ptr的信息不需要被typedef-ed去掉,而且在auto,模板和decltype之间,不需要明确的typedef。