Когда удаление экземпляра шаблона предпочтительнее, чем удаление не шаблонной перегрузки?

Предположим, у меня есть шаблон, который работает с необработанными указателями:

template<typename T>
void processPointer(T* ptr);

Я не хочу, чтобы это вызывали с void* указатели. Кажется, у меня есть два варианта. Я могу удалить не шаблонную перегрузку:

void processPointer(void*) = delete;

Или я могу удалить шаблонный экземпляр:

template<>
void processPointer<void>(void*) = delete;

Объявлять перегрузку, не связанную с шаблоном, проще (без сглаживания угловыми скобками). Есть ли причины, по которым я бы предпочел вместо этого удалить создание экземпляра шаблона?

19

Решение

Вот одна из причин в пользу версии шаблона: processPointer<void>(void*) все еще может быть вызван напрямую, избегая другой перегрузки.

17

Другие решения

Я не вижу причин для шаблонов здесь

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

4

Это может дать понимание:

#include <iostream>

struct X
{
template<typename T>
void processPointer(T* ptr) {
std::cout << "Template\n";
}

// error: explicit specialization in non-namespace scope ‘struct X’
// template<>
// void processPointer(void*) = delete;

// Overload but no specialization
// This will prevent lookup the specialization outside the class, when no
// template argument is explicitly given.  However, with an explicit
// template argument the specialization is called.
void processPointer(void*) = delete;
};

// Specialization outside the class body
template<>
void X::processPointer(void* ptr) {
std::cout << "Specialization\n";
}

int main ()
{
X x;
//error: use of deleted function ‘void X::processPointer(void*)’
//x.processPointer((void*)0);

// Explicit template argument:
x.processPointer<void>((void*)0);
}

Вывод: ответ @Casey верен.

4

Предположим, вы хотите передать аргумент pointer типа void* (или просто nullptr) на ваш processPointer функция, и вы также хотите вызвать его специализацию для типа Type, Тогда вам следует написать

processPointer(static_cast<Type>(pointer));

за

void processPointer(void*) = delete;

Но для

template<>
void processPointer<void>(void*) = delete;

Вы можете написать код, который намного короче:

processPointer<Type>(pointer);

Таким образом, оба варианта могут быть использованы в разных случаях.

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

template<typename T, typename U>
void processPointer(T* ptr1, U* ptr2);

Вы не хотите, чтобы это вызывали с void* указатели в качестве первого аргумента. Частичная специализация шаблонов функций не разрешена в C ++, поэтому этот код неверен:

template<typename U>
void processPointer<void, U>(void*, U*) = delete;

И вы должны использовать другой:

template<typename U>
void processPointer(void*, U*) = delete;
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector