4

Можно создать дубликат:
Priority when choosing overloaded template functions in C++C++ разрешение перегрузки функции относительно шаблонного типа и иерархии классов

шаблонного функция дает мне удобство для работы на различных типах:

template<typename T> void destroy(T* obj) { 
    delete obj; 
} 

Но в какой-то момент я хочу сделать некоторую специализацию в иерархии классов у:

class Base { virtual void doSomething(); }; 
class Derived : public Base {}; 
void destroy(Base* obj) { 
    obj->doSomething(); 
    delete obj; 
} 

Желаемая специализированная функция сделала вызывается, если я пропуск точного типа Base*, однако правила разрешения перегрузки, кажется, предпочитает общую шаблонную версию вместо выполнения статического вверх бросок, если я пас Derived* в void detroy().

Конечно, я могу сделать все перегруженные функции для всех возможных производных типов, но он менее обслуживаем.

Я использую Visual C++ 2008, есть ли какой-либо путь вокруг вышеупомянутой проблемы?

+0

Только что нашел аккуратный ответ на ту же проблему в переполнении стека: [Приоритет при выборе перегруженных функций шаблона в C++] (http://stackoverflow.com/questions/1332678/priority-when-choosing-overloaded-template-functions -in-c) –

+0

Однако ваша функция уничтожения имеет проблемы. Он также будет вызываться для типа массива 1D, и вы можете приземлиться на «delete» вместо «delete []», что является неопределенным поведением. – Chubsdad

+0

Op допускает, что Q должен быть закрыт как дубликат. –

ответ

0

Там нет такого понятия, как Visual C++ 2009.

Вы можете специализироваться вашу функцию с другим шаблоном и использовать SFINAE, чтобы соответствовать только подтипы базы. Но я не знаю причин, по которым компилятор предпочел бы вторую версию, обычно специализация должна быть «лучше», чтобы ее можно было выбрать.

В качестве альтернативы вы можете использовать класс SFINAE и класс вспомогательных признаков, чтобы предотвратить использование поддиректории базовых классов. Если вам нужен пример этого, спросите.

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

5

При прочих равных условиях разрешение перегрузки предпочитает функции nontemplate для работы с шаблонами. Однако в этом случае все вещи не равны. Чтобы соответствовать вашей перегрузке для Base*, требуется преобразование указателя на основе базы; преобразование не требуется для соответствия шаблону функции. Таким образом, шаблон функции выбирается для Derived*.

«Простое», хотя, вероятно, решение с ошибкой, должно было сделать ваш Derived* до Base*, прежде чем вы вызовете функцию.

Вы могли бы теоретически по крайней мере принять подход SFINAE, как предполагает Бен, но вам придется явно отключить шаблон общей функции для любых типов, для которых вы предоставляете специализации, иначе вы получите недоучеты перегрузки. Это еще более непостижимо и подвержено ошибкам, чем явный подход к литографии. (Хотя, кто-то здесь может знать другой способ обойти неоднозначность перегрузки, мне было бы интересно узнать, есть ли там).

Смежные вопросы