Calling a template method from another template method in C ++?

I am currently having a problem with templates. I have this public class that implements the template method:

namespace Private { class InternalClass; } namespace Public { class PublicClass { public: PublicClass(); virtual ~PublicClass(); template<class T> bool Add(bool primary); private: Private::InternalClass* _pInternal; }; template<class T> bool PublicClass::Add(bool primary) { return _pInternal->Add<T>(primary); } } 

The inner class is implemented as follows:

 namespace Private { class InternalClass { public: InternalClass(); virtual ~InternalClass(); template <class T> bool Add(bool primary); }; template<class T> bool InternalClass::Add(bool primary) { return false; } } 

Since this inner class header will not be available with the provided sources, I have to forward it to the PublicClass header, and I will add the include in PrivateClass.h to the PublicClass.cpp file.

1) Any idea why I am getting the following error:

error: member access to partial type 'Private :: InternalClass' / note: forward> declaration 'Private :: InternalClass'

2) What would be the best way to hide the implementation of PublicClass :: Add ()?

UPDATED

The cause of the error is 1) because of this , as pointed out by Cornstalks.

For 2), how can I hide my implementation without including PrivateClass.h in the PublicClass header file?

+5
source share
1 answer

You have a very interesting problem - you want to implement the PImpl Idiom , where the private class is the template method. Well, this can be solved, it means that you can hide the implementation of the template, but only when you know what types will be used to create your Add<T> method in your program.

Say your template will only work with AClass and BClass . Then you can split your files as follows (comments are embedded):

Public.h file :

 #ifndef PUBLIC_H #define PUBLIC_H // Forward declaration ! It sufficient in this case ! namespace Private { class InternalClass; } // Declare all classes your Add<T> method should work with struct AClass {}; struct BClass {}; namespace Public { class PublicClass { public: PublicClass() {} virtual ~PublicClass() {} template <typename T> bool Add(bool primary); // DO NOT implement this method, just declare private: Private::InternalClass* _pInternal; }; // "Explicit instantiation declarations", for each type the method will work with: extern template bool PublicClass::Add<AClass>(bool primary); extern template bool PublicClass::Add<BClass>(bool primary); } #endif 

Public.cpp file :

 #include "public.h" // NOTE: this is hidden in CPP file, noone will see your implementation namespace Private { class InternalClass { public: InternalClass() {} virtual ~InternalClass() {} template <typename T> bool Add(bool primary); }; // Magic! Here is the actual implementation of your private method template <typename T> bool InternalClass::Add(bool primary) { return false; } } namespace Public { // Original definition moved to CPP file ! template <typename T> bool PublicClass::Add(bool primary) { return _pInternal->Add<T>(primary); } // And again list the allowed types, this time using "explicit instantiation definitions" template bool PublicClass::Add<AClass>(bool primary); template bool PublicClass::Add<BClass>(bool primary); } 

Main.cpp file :

 #include "public.h" int main() { Public::PublicClass pc; pc.Add<AClass>(true); // works ! pc.Add<BClass>(false); // works ! // pc.Add<int>(true); linker error as expected, // becuase there is no explicit instantiation for Add<int> return 0; } 
+3
source

Source: https://habr.com/ru/post/1201100/


All Articles