Template and overloads

  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 a public interface for a class. Underlying data structures don't matter. Everything will work just fine when Key1 and Key2 are of different types. If they end up being the same type, the overloads will likely be impossible. Am I right thinking this?

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

EDIT: Here a more in depth sample

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

对于相同密钥类型的情况,您可以部分专门化模板,例如

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

I think you have to use partial specialization with 2 parameters, but it is not convenient because you have to use 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 single interface with 3 template parameters but getting different specializations:

DualMultimapCache<int, double, int> t1; // DualMultimapCache template impl
DualMultimapCache<int, int, int> t2;    // DualMultimapCache template 
                                        // specialization impl
链接地址: http://www.djcxy.com/p/40990.html

上一篇: 了解ShinyServer上托管的RShiny应用程序的可伸缩性

下一篇: 模板和重载