Шаблонная специализация отдельных участников?
Можно ли специализировать определенные члены classа шаблона? Что-то вроде:
template struct X { void Specialized(); }; template void X::Specialized() { ... } template void X::Specialized() { ... }
Конечно, этот код недействителен.
- Неопределенная эталонная ошибка для метода шаблона
- Как заполнить сетку WPF на основе двумерного массива
- Как легко отобразить перечислимые переменные c ++ в строки
- C ++: как требовать, чтобы один тип шаблона был получен из другого
- Почему разрешена частичная специализация шаблона вложенного шаблона, а полная - нет?
- Почему аргумент шаблона не может быть выведен, если он используется в качестве параметра шаблона для другого шаблона?
- Поддерживает ли C ++ счетчики времени компиляции?
- Как ссылаться на ресурс CSS / JS / image в шаблоне Facelets?
- Может кто-нибудь объяснить этот код шаблона, который дает мне размер массива?
- Общее решение Ruby для SQLite3 «LIKE» или PostgreSQL «ИЛИКЕ»?
- Исходное и наследование в Android
- WPF: как настроить SelectionBoxItem в ComboBox
- доступ к защищенным членам суперclassа в C ++ с помощью шаблонов
Вы можете специализироваться только на нем, предоставляя все аргументы шаблона. Разрешена частичная специализация для функций-членов шаблонов classов.
template struct X { void Specialized(); }; // works template <> void X::Specialized() { ... }
Обходной задачей является внедрение перегруженных функций, которые имеют преимущество по-прежнему в одном classе, и поэтому они имеют одинаковый доступ к переменным-членам, функциям и материалам
// "maps" a bool value to a struct type template struct i2t { }; template struct X { void Specialized() { SpecializedImpl(i2t()); } private: void SpecializedImpl(i2t) { // ... } void SpecializedImpl(i2t) { // ... } };
Обратите внимание, что, перейдя к перегруженным функциям и нажав параметры шаблона в параметр функции, вы можете произвольно «специализировать» свои функции, а также при необходимости их планировать. Другой распространенный метод – отнестись к шаблону classа, определенному отдельно
template struct SpecializedImpl; template struct SpecializedImpl { static void call() { // ... } }; template struct SpecializedImpl { static void call() { // ... } }; template struct X { void Specialized() { SpecializedImpl::call(); } };
Я считаю, что обычно требуется больше кода, и я считаю, что функция перегрузки легче обрабатывать, в то время как другие предпочитают отложить путь к шаблону classа. В конце концов, это вопрос вкуса. В этом случае вы могли бы разместить этот другой шаблон внутри X
также как вложенный шаблон – в других случаях, когда вы явно специализируетесь, а не только частично, то вы не можете этого сделать, потому что вы можете размещать явные специализации только в области пространства имен, не в class.
Вы также можете создать такой шаблон SpecializedImpl
только для целей перегрузки функции (тогда он работает аналогично i2t
), как показывает следующий вариант, который также оставляет первую переменную параметра (поэтому вы можете называть ее другими типами – не просто с параметрами шаблона текущего экземпляра)
template struct X { private: // maps a type and non-type parameter to a struct type template struct SpecializedImpl { }; public: void Specialized() { Specialized(SpecializedImpl()); } private: template void Specialized(SpecializedImpl) { // ... } template void Specialized(SpecializedImpl) { // ... } };
Я думаю, что иногда откладывание на другой шаблон лучше (когда дело доходит до таких случаев, как массивы и указатели, перегрузка может быть сложной и просто пересылка в шаблон шаблона мне была проще), а иногда просто перегрузка внутри шаблона лучше – особенно если вы действительно пересылаете аргументы функции, и если вы касаетесь переменных-членов classов.
Это то, что я придумал, не так уж плохо 🙂
//The generic template is by default 'flag == false' template struct something { void doSomething() { std::cout << "something. flag == false"; } }; template struct something : public something { void doSomething() // override original dosomething! { std::cout << "something. flag == true"; } }; int main() { something falseSomething; something trueSomething; falseSomething.doSomething(); trueSomething.doSomething(); }