Специализация шаблона и класс шаблона наследования от другого класса шаблона

У меня есть несколько вопросов о следующем коде:

template<typename T>
class Base;

template<typename T, typename P>
class Base<T(P)> {

};

template<typename T>
class Derived;

template<typename T, typename P>
class Derived<T(P)> : public Base<T(P)> {

};
  1. Специализация класса Derived<T(P)> наследуется от класса template<typename T> class Base или от класса template<typename T, typename P> class Base<T(P)>?

  2. Как называется, когда я связываю параметры шаблона T и P специализации класса Derived<T(P)> с параметром шаблона T из class Base.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
738
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

  1. Класс, созданный из шаблона Derived<T(P)>, наследуется от класса, созданного из Base<T(P)>. Поскольку тип T(P) соответствует вашей Base частичной специализации, этот шаблон будет использоваться для создания экземпляра класса, от которого будет наследоваться.

  2. Это просто называется наследованием. Ничего особенного там не происходит. Вы просто создаете экземпляр шаблона Base с типом T(P) и наследуете полученный класс.


Base<T(P)> будет создан, когда будет создан экземпляр Derived<T(P)>, поэтому Derived<void(int)> наследуется от Base<void(int)>. Оба этих экземпляра будут проходить через один и тот же набор правил, чтобы выяснить, какой шаблон использовать для создания экземпляра этого класса.

Вы можете запутаться, думая, что T(P) — это какой-то специальный шаблон. Это не. Это просто тип «функции, которая возвращает T и принимает один аргумент типа P». Конечно, подобные типы редко встречаются вне шаблонов, но в других местах они вполне законны. то есть

using FuncType = void(int);

// These two declarations are exactly the same
void doAThing(FuncType* callback);
void doAThing(void(*callback)(int));
Ответ принят как подходящий
  1. Class specialization Derived<T(P)> inherits from class template<typename T> class Base or from class template<typename T, typename P> class Base<T(P)>?

Технически ни то, ни другое. Класс или шаблон класса никогда не наследуется от шаблона, а только от одного конкретного типа базового класса. То есть Derived<int(float&)> наследует Base<int(float&)> и так далее. Этот базовый класс создается из наиболее специализированного объявления, связанного с Base для этих конкретных типов. Важность этого различия возникает, если есть дополнительные частичные специализации или явные специализации.

Если я немного изменю ваш пример,

template<typename T> // #1
class Base;

template<typename T, typename P> // #2
class Base<T(P)> {
public:
    static const int mem1 = 1;
};

template<typename T>
class Derived;

template<typename T, typename P>
class Derived<T(P)> : public Base<T(P)> {
};

class SomethingElse {};

template<typename P> // #3
class Base<SomethingElse(const P&)> {
public:
    static const long long mem2 = 2;
};

using ThingType = Derived<SomethingElse(const std::string&)>;
const auto A = ThingType::mem1; // Error!
const auto B = ThingType::mem2; // OK

Неправильно говорить, что частичная специализация Derived<T(P)> наследует частичную специализацию Base<T(P)>, поскольку тип примера Derived<SomethingElse(const std::string&)> использует эту Derived частичную специализацию, но не использует эту Base частичную специализацию вообще. Base<T(P)> просто означает шаблон с именем Base, с любым определением специализации для Base, которое лучше всего соответствует аргументу шаблона T(P). Решение о том, что означает базовый класс Base<T(P)>, принимается независимо для каждого конкретного набора аргументов шаблона при создании экземпляра каждой специализации Derived.

  1. What the name of when I'm binding template parameters T and P of class specialization Derived<T(P)> with template parameter T of class Base.

Я не знаю никакого термина для этого, кроме того, что вы используете зависимый составной тип. (Зависимый = зависит от одного или нескольких параметров шаблона; Составной = тип T(P) включает в себя другие типы T и P.) Это также делает Base<T(P)> зависимым базовым классом в определении Derived<T(P)>, то есть компилятор не будет искать там простые идентификаторы, и вам нужно использовать this->name или Base::name, чтобы сделать такие имена действительными. Также важно, чтобы параметры шаблона находились в «выводимых контекстах» внутри аргументов шаблона специализации.

Почему это так сложно? Пишу диссертацию и не могу найти точного определения и объяснения такой конструкции.

TupleCats 30.05.2019 00:26

@DarkHell Я до сих пор точно не знаю, для чего тебе нужен термин.

aschepler 30.05.2019 00:39

Я думал, что у такого явления есть срок.

TupleCats 30.05.2019 00:44

Впервые я сталкиваюсь с синтаксисом типа Base<T(P)> (с этим "(P)"). Могу я спросить, что такое ключевое слово для Google?

bluk 02.11.2020 08:23

@bluk T(P) вот тип функции. Если у нас есть функция int f(double);, то Base<decltype(f)> совпадает с Base<int(double)>, и этот тип будет использовать частичную специализацию путем вывода T=int и P=double.

aschepler 02.11.2020 16:06

Другие вопросы по теме