Подтвердить что ты не робот

Вызовите неспециализированную версию функции, когда она специализируется на С++?

Скажем, у меня есть шаблон:

template <typename T>
class foo {
  void do_someting(T obj) {
    // do something generic...
  }
};

и я хочу специализировать do_something, но внутри него я хочу вызвать "нормальную" функцию do_something:

template<>
void foo<MyObj>::do_something(MyObj obj) {
  // do something specific...
  // and ALSO do something generic!
}

Есть ли способ ссылаться на обычную версию do_something внутри моей специализированной функции? Или мне просто нужно скопировать код?

(Я знаю, что я мог бы рефакторировать foo таким образом, что у меня не было бы этой точной проблемы, но, как бы то ни было, я не могу реально изменить "реальный" foo, поскольку он сильно разделяет код.)

4b9b3361

Ответ 1

Нет. Ваша специализация - единственное определение, которое будет существовать для аргумента типа MyObj. Но рассмотрите возможность изменения шаблона foo таким образом, который будет прозрачным для текущих пользователей шаблона:

template<typename T>
class foo {
  void prelude(T &obj){ // choose a better name
    /* do nothing */
  }
  void do_something(T obj){
    prelude(obj);
    // do something generic...
  }
};

Затем определите специализацию для прелюдии:

template<>
void foo<MyObj>::prelude(MyObj &obj){
  // do something specific
}

Это похоже на структуру основного использования для частных виртуальных участников. (На самом деле это не так. Но это вдохновило меня на этот ответ.)

Ответ 2

Вы также можете рассмотреть тип, который не является MyObj, но неявно преобразуется в него, но лучший способ - рефакторинг и, возможно, извлечение общего общего.

#include <iostream>
#include <boost/ref.hpp>
typedef int MyObj;


template <typename T>
struct foo {
  void do_something(T obj) {
    // do something generic...
    std::cout << "generic " << obj << '\n';
  }
};

template<>
void foo<MyObj>::do_something(MyObj obj) {
  // do something specific...
  std::cout << "special " << obj << '\n';
  // and ALSO do something generic!
  foo<boost::reference_wrapper<MyObj> >().do_something(boost::ref(obj));
}

int main()
{
    foo<int> f;
    f.do_something(10);
}

Ответ 3

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

template <typename T>
class foo 
{
  void do_something(T obj) 
  {
     do_something_impl(obj);
  }

  void do_something_impl(T obj)
  {
    // do something generic...
  }
};

Теперь специализация может вызывать общую версию без проблем:

template<>
void foo<MyObj>::do_something(MyObj obj) 
{
  // do something specific...
  do_something_impl(obj); //The generic part
}

Я думаю, что это ближе к вашим первоначальным намерениям, чем Стив М. отвечает, и это то, что я делаю, когда сталкиваюсь с этой проблемой.