У меня есть несколько вопросов о следующем коде:
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)> {
};
Специализация класса Derived<T(P)> наследуется от класса template<typename T> class Base или от класса template<typename T, typename P> class Base<T(P)>?
Как называется, когда я связываю параметры шаблона T и P специализации класса Derived<T(P)> с параметром шаблона T из class Base.





Класс, созданный из шаблона Derived<T(P)>, наследуется от класса, созданного из Base<T(P)>. Поскольку тип T(P) соответствует вашей Base частичной специализации, этот шаблон будет использоваться для создания экземпляра класса, от которого будет наследоваться.
Это просто называется наследованием. Ничего особенного там не происходит. Вы просто создаете экземпляр шаблона 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));
- Class specialization
Derived<T(P)>inherits from classtemplate<typename T> class Baseor from classtemplate<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.
- What the name of when I'm binding template parameters
TandPof class specializationDerived<T(P)>with template parameterTof class Base.
Я не знаю никакого термина для этого, кроме того, что вы используете зависимый составной тип. (Зависимый = зависит от одного или нескольких параметров шаблона; Составной = тип T(P) включает в себя другие типы T и P.) Это также делает Base<T(P)> зависимым базовым классом в определении Derived<T(P)>, то есть компилятор не будет искать там простые идентификаторы, и вам нужно использовать this->name или Base::name, чтобы сделать такие имена действительными. Также важно, чтобы параметры шаблона находились в «выводимых контекстах» внутри аргументов шаблона специализации.
@DarkHell Я до сих пор точно не знаю, для чего тебе нужен термин.
Я думал, что у такого явления есть срок.
Впервые я сталкиваюсь с синтаксисом типа Base<T(P)> (с этим "(P)"). Могу я спросить, что такое ключевое слово для Google?
@bluk T(P) вот тип функции. Если у нас есть функция int f(double);, то Base<decltype(f)> совпадает с Base<int(double)>, и этот тип будет использовать частичную специализацию путем вывода T=int и P=double.
Почему это так сложно? Пишу диссертацию и не могу найти точного определения и объяснения такой конструкции.