Специализация шаблонной функции для конкретного интерфейса - PullRequest
2 голосов
/ 19 сентября 2010

У меня есть следующий фрагмент кода:

class ICookable
{
public:
    virtual void CookMe () = 0;
    virtual ~ICookable () {};
};

class Egg : public ICookable
{
public:
    virtual void CookMe () {cout << "Egg cooked!" << endl;}
};

template <class T>
void Cook (T&)
{
    cout << "Item Uncookable!" << endl;
}

template <>
void Cook (ICookable& c)
{
    c.CookMe ();
}

int _tmain(int argc, _TCHAR* argv[])
{
    Egg egg;
    Cook (egg);
    return 0;
}

Я хочу, чтобы функция Cook работала по-разному в зависимости от того, наследуется ли ее параметр от интерфейса ICookable или нет.Однако в приведенном выше примере я получаю сообщение «Item Uncookable» для параметра Egg, если только я не пишу вручную:

Cook<ICookable> (egg);

Есть ли способ, позволяющий компилятору автоматически выбирать правильную реализацию для потомков ICookable?

1 Ответ

3 голосов
/ 19 сентября 2010

Отправка во время компиляции через boost :: is_base_of и частичную специализацию шаблона класса:

template<class T, class _>
struct CookDetail {
  static void cook(T& obj) {
    cout << "uncookable\n";
  }
};
template<class T>
struct CookDetail<T, boost::true_type> {
  static void cook(ICookable& obj) {
    obj.CookMe();
  }
};

template<class T>
void cook(T& obj) {
  return CookDetail<T, boost::is_base_of<ICookable, T> >::cook(obj);
}

Тем не менее, наличие «работы» cook (non_icookable_obj) для меня является ошибкой. Я бы предпочел ошибку времени компиляции для попытки приготовить неприготовленное.

Обратите внимание, что то, что вы пробовали, терпит неудачу, потому что именно так работает разрешение функций. Точное совпадение по шаблону (cook (Egg &)) считается лучше, чем шаблон, требующий преобразования (cook (ICookable &)). Подробности в FCD , если вы хотите загадочные технические детали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...