Using pimpl with Templated Class and explicitly in

2019-08-06 04:59发布

How do I use pimpl for a templated class, when I explicitly instantiate the templates?

All I need is an example code.

What I have tried is:

// MyTemplatedClass.h

template< class T >
class MyTemplatedClass
{
private:
    class Impl;
    Impl* _pimpl;

public:
    void PublicMethod();
}

Here my implementation goes:

// MyTemplatedClass.cpp

template< class T >
class MyTemplatedClass<T>::Impl
{
    public:
        void PublicMethod();
}

template <class T>
void MyTemplatedClass<T>::Impl::PublicMethod()
{
    ...
}

Forwarding method call to implementation class:

template< class T >
void MyTemplatedClass<T>::PublicMethod()
{
    _pimpl->PublicMethod();
}

Explicit instantiation: Example with int and double:

template class MyTemplatedClass< int >;
template class MyTemplatedClass< double >;

But it doesn't seem to work.

2条回答
啃猪蹄的小仙女
2楼-- · 2019-08-06 05:11

Methods of a template class always have to be defined in the header. You cannot have a MyTemplatedClass.cpp as compilation unit on its own. What you can do is to #include the file containing the definitions of the methods at the end of MyTemplatedClass.h so that declaration and definition are at least separated at file level. So your problem may be fixed by adding

#include "MyTemplatedClass.cpp"

at the end of MyTemplatedClass.h.

I use pimpls with template classes in my own code, it works for me that way. Your code looks about right - I'd use a std::unique_ptr for pimpl, but I don't see any problems with how you're doing it.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-08-06 05:20

This would answer your question, but I doubt it does what you hoped to achieve. I suspect you would want to declare the template implementation outside the scope of MyTemplatedClass. It might be a better design to inherit from the template implementation instead of having it as a member variable.

If you compiler does not support extern template declarations I cannot see that having a template pointer to implementation adds any value. You would after all have to have the implementation details you wanted to hide away in the header file anyway.

#include <iostream>

template < class T > class MyTemplatedClass {
private:
  template < class U> class Impl {
  public:
     void ImplPublicMethod() {
           std::cout << "Standard implementation" << std::endl;
           }
  };

  Impl<T> * _pimpl;
public:
  MyTemplatedClass() : _pimpl(new Impl<T>) { }
  ~MyTemplatedClass() { delete _pimpl; }
  void publicMethod() {
     _pimpl->ImplPublicMethod();
  }
};

template<> class MyTemplatedClass<int> {
private:
  class Impl {
  public:
     void ImplPublicMethod() {
          std::cout << "Integer specialisation" << std::endl;
     };
 };

 Impl * _pimpl;
public:
  MyTemplatedClass() : _pimpl(new Impl) { }
  ~MyTemplatedClass() { delete _pimpl; }
  void publicMethod() {
     _pimpl->ImplPublicMethod();
  }
};

int main(int argc, char ** argv) {

   MyTemplatedClass<char> charVersion;
   charVersion.publicMethod();

   MyTemplatedClass<int> intVersion;
   intVersion.publicMethod();

   return 0;
}
查看更多
登录 后发表回答