1

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.

Zythos
  • 180
  • 2
  • 8
abaldur
  • 29
  • 1
  • 3
  • 1
    When something "doesn't [seem to] work," *always* tell us exactly *how* it "doesn't [seem to] work." In other words, what errors are you getting? – Angew is no longer proud of SO Aug 13 '13 at 08:05
  • When I try to forward the PublicMethod, the compiler doesn't detect my PublicMethod. _pimpl-> should give me a list of available methods, but no one exists. – abaldur Aug 13 '13 at 08:14
  • 2
    You're talking about your IDE, right? The code analysis in your IDE and your compiler are generally two different things; if your IDE just does not show you that a method is available, that does not necessarily mean that the compiler wouldn't find it if you use it there. – flyx Aug 13 '13 at 08:20
  • It gives me the error: C2227: left of '->PublicMethod' must point to class/struct/union/generic type 1> MyTemplatedClass.cpp(65) : while compiling class template member function 'void MyTemplatedClass::PublicMethod()' – abaldur Aug 13 '13 at 08:28
  • @user1507569 Seems as if the compiler can't find the proper definition of `_pimpl`. Try prefixing it with `this->`. – Angew is no longer proud of SO Aug 13 '13 at 08:33
  • It gives me about the same error. – abaldur Aug 13 '13 at 08:36
  • Does it make a difference if you add the ';' at the end of the class definitions? Otherwise, what compiler are you using? – Come Raczy Aug 13 '13 at 08:58

2 Answers2

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;
}
Lev Landau
  • 788
  • 3
  • 16
  • I must have had a brain haemorrhage. A little typo made the compiler angry. The code I wrote in the question works fine. – abaldur Aug 13 '13 at 09:34
-1

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.

flyx
  • 35,506
  • 7
  • 89
  • 126
  • 3
    -1: Member functions of template classes always have to be defined in the header *unless they are explicitly instantiated somewhere in the program.* The OP is doing the explicit instantiation, so this doesn't apply here. – Angew is no longer proud of SO Aug 13 '13 at 08:28