специализация шаблона для всех подклассов - PullRequest
12 голосов
/ 01 октября 2011

Я хотел бы определить специализацию шаблона C ++, которая применяется ко всем подклассам данного базового класса.Это возможно?

В частности, я хотел бы сделать это для хеша STL <>.hash <> определяется как пустой параметризованный шаблон и семейство специализаций для определенных типов:

template<class _Key>
  struct hash { };

template<>
  struct hash<char>
  {
    size_t
    operator()(char __x) const
    { return __x; }
  };

template<>
  struct hash<int>
  {
    size_t
    operator()(int __x) const
    { return __x; }
  };
...

Я хотел бы определить что-то вроде этого:

template<class Base>
  struct hash {
    size_t operator()(const Base& b) const {
      return b.my_hash();
    }
  };

class Sub : public Base {
  public:
    size_t my_hash() const { ... }
};

и иметь возможностьчтобы использовать его так:

hash_multiset<Sub> set_of_sub;
set_of_sub.insert(sub);

Однако мой хеш-шаблон конфликтует с универсальным шаблоном из STL.Есть ли способ (возможно, с использованием признаков) для определения специализации шаблона, который применяется ко всем подклассам данного базового класса (без изменения определений STL)?

Обратите внимание, что я знаю, что могу сделать это с помощью некоторого дополнительного шаблонапараметры всякий раз, когда нужна эта спецификация хэша, но я бы хотел избежать этого, если это возможно:

template<>
  struct hash<Base> {
    size_t operator()(const Base& b) const {
      return b.my_hash();
    }
  };

....

// similar specialization of equal_to is needed here... I'm glossing over that...
hash_multiset<Sub, hash<Base>, equal_to<Base> > set_of_sub;
set_of_sub.insert(sub);

Ответы [ 2 ]

1 голос
/ 02 октября 2011

Решение состоит в том, чтобы использовать SFINAE, чтобы решить, разрешить или нет вашу специализацию в зависимости от структуры наследования классов. В Boost вы можете использовать enable_if и is_base_of для реализации этого.

0 голосов
/ 07 февраля 2012

Это было лучшее, что я мог сделать:

template<>
  struct hash<Sub> : hash<Base> {
  };

Я немного волнуюсь, что мне не нужно было делать operator() виртуальным.

...