Pattern and Overload

template<class Key1, class Key2, class Type> class DualMultimapCache { public: std::list<std::reference_wrapper<Type>> get(Key1 const & key); std::list<std::reference_wrapper<Type>> get(Key2 const & key); template<class ...Args> Type & put(Key1 const & key, Args const & ...args); template<class ...Args> Type & put(Key2 const & key, Args const & ...args); }; 

Here I have an open interface for the class. The underlying data structures do not matter. Everything will work fine when Key1 and Key2 are of different types. If they end up being the same type, overloads are likely to be impossible. Am I correct in this?

If I, is there a way to split the overloads while keeping the signature as clean as possible?

EDIT: here's a more detailed example

  template<class Key1, class Key2, class Type> class DualMultimapCache { public: std::list<std::reference_wrapper<Type>> get(Key1 const & key); std::list<std::reference_wrapper<Type>> get(Key2 const & key); template<class ...Args> Type & put(Key1 const & key, Args const & ...args); template<class ...Args> Type & put(Key2 const & key, Args const & ...args); private: std::unordered_multimap<Key1, std::reference_wrapper<Type>> map_Key1; std::unordered_multimap<Key2, std::reference_wrapper<Type>> map_Key2; }; template<class Key1, class Key2, class Type> std::list<std::reference_wrapper<Type>> DualMultimapCache<Key1, Key2, Type>::get(Key1 const & key) { auto its = map_Key1.equal_range(key); if (its.first == map.cend() && its.second == map.cend()) throw std::out_of_range(); else return { its.first, its.second }; } template<class Key1, class Key2, class Type> std::list<std::reference_wrapper<Type>> DualMultimapCache<Key1, Key2, Type>::get(Key2 const & key) { auto its = map_Key2.equal_range(key); if (its.first == map.cend() && its.second == map.cend()) throw std::out_of_range(); else return { its.first, its.second }; } 
+7
c ++ templates method-overloading overload-resolution class-template
source share
2 answers

You can partially customize the template for the case of the same key type, for example.

 template <typename Key, typename Type> class DualMultimapCache<Key, Key, Type> { public: std::list<std::reference_wrapper<Type>> get(Key const & key); template<class ...Args> Type & put(Key const & key, Args const & ...args); }; 
+3
source share

I think you need to use partial specialization with two parameters, but this is not convenient because you need to use a slightly different interface. To solve this problem, I suggest using SFINAE

 template<typename Key1, typename Key2, typename Type, typename Enable = void > class DualMultimapCache { public: std::list<std::reference_wrapper<Type>> get(Key1 const & key); std::list<std::reference_wrapper<Type>> get(Key2 const & key); template<class ...Args> Type & put(Key1 const & key, Args const & ...args); template<class ...Args> Type & put(Key2 const & key, Args const & ...args); }; template<typename Key1, typename Key2, typename Type > class DualMultimapCache < Key1, Key2, Type, typename std::enable_if<std::is_same<Key1, Key2>::value>::type > { public: std::list<std::reference_wrapper<Type>> get(Key1 const & key); template<class ...Args> Type & put(Key1 const & key, Args const & ...args); }; 

And you can use one interface with three template parameters, but getting different specializations:

 DualMultimapCache<int, double, int> t1; // DualMultimapCache template impl DualMultimapCache<int, int, int> t2; // DualMultimapCache template // specialization impl 
0
source share

All Articles