Явные специализации шаблонов функций не должны использоваться.
Явные специализации шаблонов функций не должны использоваться.
Явная специализация шаблонов функций может вызвать неожиданные проблемы с разрешением перегрузки на C++. Разрешение перегрузки:
Первые поиски нешаблона, простая функция, которая имеет соответствующий список параметров.
Если такая функция не доступна, разрешение перегрузки выбирает самый близкий шаблон функции соответствия.
После того, как шаблон функции выбран, компилятор ищет подходящую специализацию шаблона.
Специализация шаблона не изменяет порядок процесса разрешения перегрузки, который может привести к запутывающему и неожиданному поведению. Рассмотрите фрагмент кода:
//(a) base template template<class T> void f( T ); //(b) specialization of (a) template<> void f<>(int*); //... //(c) overloads (a) template<class T> void f( T* ); //... main(){ int *p; f( p ); }
f()
вызван int*
в main()
, вы можете ожидать специализацию для int*
, отмеченный (b), чтобы быть названным. Компилятор разрешает вызов f()
можно следующим образом:
Компилятор ищет простую функцию с входным типом int*
.
Поскольку нет такой функции, компилятор ищет шаблон функции, который имеет самый близкий список параметров соответствия.
Шаблон (c), который берет типовой указатель, как введено, является самым близким соответствием для f(int*)
.
Шаблон (c) не специализирован. Процесс разрешения перегрузки останавливает и вызывает шаблон в (c).
Даже при том, что специализированный шаблон для int*
вход типа задан в (b), перегрузка решает к шаблону в (c) вместо этого, который может быть неожиданным.
Когда вы специализируете шаблон перегруженной функции, процесс разрешения перегрузки может стать более сбивающим с толку. То, которое среди перегруженных шаблонов специализировано, зависит от порядка объявления. Рассмотрите фрагмент кода:
//(a) template <typename T> void F1(T t){} //(b) template <typename T> void F1(T* p){} //(x): Specialization of template template <> void F1<>(uint16_t* p){}
//(a) template <typename T> void F1(T t){} //(x): Specialization of template template <> void F1<>(uint16_t* p){} //(b) template <typename T> void F1(T* p){}
Чтобы постараться не путать код и неожиданное поведение, постарайтесь не специализировать шаблоны функций. Если необходимо специализировать шаблон функции, то запишите один шаблон функции, который делегирует к шаблону класса. Например, в этом коде, шаблоне функции f()
делегаты в классе f_implementation
.
template<class T> class f_implementation; template<class T> void f( T t ) { FImpl<T>::f( t ); //Don't specialize function template } template<class T> class f_implementation { static void f( T t ); // Specializing class templates is permissible. }
Если вы явным образом специализируете шаблон функции, Polyspace® отмечает шаблон функции.
Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.
Группа: шаблоны |