模板类的智能指针?

时间:2011-09-03 02:34:11

标签: c++ templates smart-pointers

我怀疑我不能使用PIMPL模式直接执行此操作。是否可以有一个指向模板类的智能指针?我无法通过转动shared_ptr声明上的旋钮进行编译。

// ============Foo.h ============
// Forward declare the implementation
template <typename T> class FooImpl;

class Foo
{
  public:
    Foo getInstance(const string& fooType);
    ...
  private:
    shared_ptr< FooImpl<T> > m_impl;
};

// ============FooImpl.h ============
template <typename T>
class FooImpl
{
    ...
};

在Visual Studio 2008下:“错误C2065:'T':未声明的标识符”。我在GCC下收到类似的错误。 如果我取消参数化FooImpl(以便FooTempl继承自FooImpl),代码将被编译。

我怀疑我不能对智能指针进行参数化,但我可能错了。

编辑:第二个 Visual Studio错误更有说服力:“错误C3203:'FooImpl':非专用类模板不能用作模板参数'T'的模板参数,预期a真实的类型“

杰夫

5 个答案:

答案 0 :(得分:3)

我不完全确定你想要完成什么,但这有帮助吗?

尝试1:

// ============Foo.h ============
// Forward declare the implementation

template <typename T> class FooImpl;

template<class C>
class Foo
{
  public:
    Foo getInstance(const string& fooType);
    ...
  private:
    shared_ptr< FooImpl<C> > m_impl;
};

// ============FooImpl.h ============
template <typename T>
class FooImpl
{
    ...
};

尝试2:

// ============Foo.h ============
// Forward declare the implementation

class FooImplBase;

class Foo
{
  public:
    Foo getInstance(const string& fooType);
    ...
  private:
    shared_ptr< FooImplBase > m_impl;
};

// ============FooImpl.h ============
class FooImplBase {
  public:
    virtual void AnAPI();
    virtual int AnotherAPI();
};
template <typename T>
class FooImpl : public FooImplBase
{
    ...
};

答案 1 :(得分:1)

您做得对,只需确保T已定义。这在MSVC ++ 2010上为我编译:

#include <memory>

using namespace std;

template<class T>
class Blah {
public:
    Blah() { }
};

class Foo {
public:
    shared_ptr<Blah<int>> ptr;

    Foo() : ptr(new Blah<int>()) { }
};

如果您使用的旧编译器尚未包含C ++ 11的此功能,请更改

shared_ptr<Blah<int>> ptr;

shared_ptr<Blah<int> > ptr;

因此编译器认为>>不是正确的转变。但是C ++ 11没有这个问题。

答案 2 :(得分:1)

  

我事先并不知道我会有一个Blah,只有一个Blah。

从语言的角度来看,Blah<T>毫无意义,因为T不存在。根据您正在尝试做的事情,您可以

使Foo成为模板,以便您可以声明模板参数T

template<typename T>
class Foo
{
  public:
    Foo getInstance(const string& fooType);
    ...
  private:
    shared_ptr< FooImpl<T> > m_impl;
};

在声明T类型的变量时“修复”Foo<T>的选择;

或使FooImpl显式派生于一个共同基础:

class FooBase {
    // need to define the interface here
};

// this is a class definition whereas previously you only needed a declaration
template<typename T>
class FooImpl: public FooBase {
    // definition here
};

class Foo
{
  public:
    Foo getInstance(const string& fooType);

    // we needed the definition of FooImpl for this member
    // in addition this member is quite obviously a template
    template<typename T>
    void
    set(FooImpl<T> const& foo)
    {
        m_impl.reset(new FooImpl<T>(foo));
    }

    // not a member template!
    void
    use()
    {
        // any use of m_impl will be through the FooBase interface
    }

  private:
    shared_ptr<FooBase> m_impl;
};

对于给定的Foo实例,可以动态设置任何类型的FooImpl<T>,然后通过FooBase接口使用。{{1}}这是在C ++世界中调用的type erasure

答案 3 :(得分:1)

您发布的代码无法编译,因为TFoo的上下文中没有任何意义。编译器需要一个名为T的类型,在那里不存在...不完全确定你想要完成什么,但是下面的解决方案不会解决你的问题吗?

// ============Foo.h ============ 

class FooImplBase {
    virtual void WhateverFooImplIsSupposedToDo() = 0;
};

template <typename T> class FooImpl : public FooImplBase {
    T mInstance;
public:
    FooImpl(T const & pInstance) : mInstance(pInstance) {}
    virtual void WhateverFooImplIsSupposedToDo() 
    {
        // implementation which deals with instances of T
    }
}; 

class Foo 
{ 
  public: 
    Foo getInstance(const string& fooType) {
     // use m_impl->WhateverFooImplIsSupposedToDo...
    }    

    template < class T >
    Foo( T const & pInstance ) : m_impl(new FooImpl<T>(pInstance)) {}
  private: 
    shared_ptr< FooImplBase > m_impl; 
}; 

答案 4 :(得分:0)

我们可以使用模板编写通用的智能指针类。以下C ++代码演示相同。我们不需要调用delete'ptr',当对象'ptr'超出范围时,它的析构函数会自动生成。

#include<iostream>
using namespace std;

// A generic smart pointer class
template <class T>
class SmartPtr
{
   T *ptr;  // Actual pointer
public:
   // Constructor
   explicit SmartPtr(T *p = NULL) { ptr = p; }

   // Destructor
   ~SmartPtr() {
    cout <<"Destructor called" << endl;  
    delete(ptr);
   }

   // Overloading dereferncing operator
   T & operator * () {  return *ptr; }

   // Overloding arrow operator so that members of T can be accessed
   // like a pointer (useful if T represents a class or struct or 
   // union type)
   T * operator -> () { return ptr; }
};

int main()
{
    SmartPtr<int> ptr(new int()); // Here we can create any data type pointer just like 'int'
    *ptr = 20;
    cout << *ptr;
    return 0;
}

out put:

20

析构函数叫