Явные специализации шаблонов функций не должны использоваться
Явные специализации шаблонов функций не должны использоваться.
Явная специализация шаблонов функций может вызвать неожиданные проблемы с разрешением перегрузки на 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*
type input задан в (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® помечает шаблон функции.
Если вы ожидаете нарушения правил, но не видите его, обратитесь к разделу «Стандартные нарушения кодирования не отображаются».
Группа: Шаблоны |
Категория: Необходимый, Автоматизированный |