Using pimpl with Templated Class and explicitly instantiated templates

三世轮回 提交于 2020-01-25 06:35:26

问题


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.


回答1:


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



回答2:


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.



来源:https://stackoverflow.com/questions/18203693/using-pimpl-with-templated-class-and-explicitly-instantiated-templates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!