如何声明静态函数和typedef public,哪些不能继承?

时间:2011-02-26 11:09:27

标签: templates c++11

正如许多其他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> {};

1 个答案:

答案 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。