How to simulate a partial specialization of selected member functions based on a template parameter that is an STL container?

I am working with a class that uses STL containers as a template parameter. However, not all containers provide the same methods, so I'm trying to figure out how I can specialize specific methods based on the container used.

Example:

template<typename container> class A { private: container m_container; public: void foo(); // does something container specific // more generic methods that work with any container }; 

The following doexs code does not compile, saying "It is impossible to combine the specialization of the method", but this is approximately what I want to achieve:

 template<typename T> template<> void A<std::vector<T> >::foo() { // vector specific implementation } template<typename T> template<> void A<std::map<T> >::foo() { // map specific implementation } 

I need to support several compilers, including MSVC2010, gcc C ++ 99, the old Solaris compiler ...

The only way to find this fiasco is to implement external methods that do everything that foo to do and overload them for different types of containers. But I do not want to disclose these functions globally, is there a way to do this through specializations?

A special case when it is impossible to outsource them is constructor specializations ...

+7
c ++ templates template-specialization
source share
2 answers

Option number 1

Use tag sending:

 template <typename T> struct tag {}; template <typename container> class A { private: container m_container; template <typename T, typename Alloc> void foo_spec(tag<std::vector<T, Alloc> >) { // vector specific implementation } template <typename K, typename V, typename C, typename Alloc> void foo_spec(tag<std::map<K,V,C,Alloc> >) { // map specific implementation } public: void foo() { foo_spec(tag<container>()); } // more generic methods that work with any container }; 

Demo 1

Option number 2

Partially specialize a separate class with a static member function:

 template <typename T> struct Impl; template <typename T, typename Alloc> struct Impl<std::vector<T, Alloc> > { static void foo_spec() { // vector specific implementation } }; template <typename K, typename V, typename C, typename Alloc> struct Impl<std::map<K,V,C,Alloc> > { static void foo_spec() { // map specific implementation } }; template <typename container> class A { private: container m_container; public: void foo() { Impl<container>::foo_spec(); } // more generic methods that work with any container }; 

Demo 2

Option number 3

Derive from a partially specialized class + CRTP idioms:

 template <typename container> class A; template <typename CRTP> struct Base; template <typename T, typename Alloc> struct Base<A<std::vector<T, Alloc> > > { void foo() { // vector specific implementation A<std::vector<T, Alloc> >* that = static_cast<A<std::vector<T, Alloc> >*>(this); } }; template <typename K, typename V, typename C, typename Alloc> struct Base<A<std::map<K,V,C,Alloc> > > { void foo() { // map specific implementation A<std::map<K,V,C,Alloc> >* that = static_cast<A<std::map<K,V,C,Alloc> >*>(this); } }; template <typename container> class A : public Base<A<container> > { friend struct Base<A<container> >; private: container m_container; public: // more generic methods that work with any container }; 

Demo 3

Option number 4

Use the reverse inheritance hierarchy proposed by David Rodriguez - dribeas in the comments:

 template <typename container> class Base { private: container m_container; public: // more generic methods that work with any container }; template <typename container> class A; template <typename T, typename Alloc> class A<std::vector<T, Alloc> > : public Base<std::vector<T, Alloc> > { public: void foo() { // vector specific implementation } }; template <typename K, typename V, typename C, typename Alloc> class A<std::map<K,V,C,Alloc> > : public Base<std::map<K,V,C,Alloc> > { public: void foo() { // map specific implementation } }; 

Demo 4

+10
source share

You cannot specialize individual methods, but the whole class template:

 template<typename container> class A { ... ... template<typename T> class A<vector<T>> { 

If you want most methods to be common, and only some methods are different, you can inherit all specializations from a common base class.

 template<typename container> class A : public ABase<container> { ... ... template<typename T> class A<vector<T>> : public ABase<vector<T>> { 
+1
source share

All Articles