АТ>Прямой "короткий" ответ на вопрос не имеет никакого отношения ни к каким частичным специализациям функций. Язык просто запрещает объявление явных специализаций любых шаблонов внутри определения охватывающего шаблона класса. Этот запрет в одинаковой мере распространяется и на классы, и на функции, т.е. отсутствие частичной специализации функций тут вообще ни при чем.
Кхм. Ващет, вопрос был про template<typename T> void STest4<T>::foo<TypeH2>() { ... } (вне класса), а не про template<> void foo<TypeH1> (внутри класса)
АТ>
Здравствуйте, vopl, Вы писали:
V>Здравствуйте, σ, Вы писали:
V>>>Напрямую — никак. Это будет частичная специализация, язык такое не позволяет.
σ>>Как можно понять, что template<typename T> void STest4<T>::foo<TypeH2>() это частичная специализация?
V>Ну, понять это достаточно просто: если после подстановки аргументов шаблон воплощается в тип/значение — то это полная специализация, а если все еще остается шаблоном — то это частичная. В приведенном куске метод foo принадлежит наблону STest4<T>, то есть сам продолжает быть шаблоном, занчт — частичная специализация. Еще примеры:
Это попытка ответа с точки зрения rationale, т.е. "длинный ответ" на вопрос почему это не разрешается. И вряд ли это точное/полное rationale.
Прямой "короткий" ответ на вопрос не имеет никакого отношения ни к каким частичным специализациям функций. Язык просто запрещает объявление явных специализаций любых шаблонов внутри определения охватывающего шаблона класса. Этот запрет в одинаковой мере распространяется и на классы, и на функции, т.е. отсутствие частичной специализации функций тут вообще ни при чем. Вы получите ту же ошибку и на
(Я все время забываю, где этот запрет сформулирован в стандарте и навскидку не могу его найти.)
Явные специализации шаблонов-членов должны объявляться в namespace scope и должны делаться только для конкретных специализаций охватывающего шаблона. То есть, подчеркиваю, это ограничение в равное мере распространяется и на вложенные шаблоны классов, то есть отсутствие частичной специализации функций тут вообще ни при чем.
template <typename T> struct S
{
template <typename U> struct N {};
};
template <> template <> struct S<int>::N<double> {}; // <- Так можноtemplate <typename T> template <> struct S<T>::N<double> {}; // <- А вот так нельзя
Здравствуйте, SVV, Вы писали:
SVV>Здравствуйте, vopl, Вы писали:
V>>Здравствуйте, SVV, Вы писали:
SVV>>>как правильно написать специализацию метода?
V>>Напрямую — никак. Это будет частичная специализация, язык такое не позволяет. Но, можно нечто похожее организовать через SFINAE или через концепты SVV>... V>>Еще можно вынести специализацию в другой класс и его уже специализировать, а foo оставить обобщенным..
SVV>А как подобное провернуть с конструктором? Проблема с вызовом такого конструктора: SVV>
SVV>template<typename T>
SVV>struct STest4
SVV>{
SVV> template<typename H> STest4() requires is_same_v<H, TypeH1> { cout << "ctor(TypeH1)" << endl; }
SVV> template<typename H> STest4() requires is_same_v<H, TypeH2> { cout << "ctor(TypeH2)" << endl; }
SVV> ...
SVV>};
SVV>STest4<float> st5_1<TypeH1>();//warning C4930: 'STest4<float> st5_1(void)': prototyped function not called (was a variable definition intended?)
SVV>STest4<float> st5_2<TypeH2>();//warning C4930: 'STest4<float> st5_1(void)': prototyped function not called (was a variable definition intended?)
SVV>
SVV>код компилируется, но конструктор не вызывается.
Не вызывается, потому что st5_1 и st5_2 — это не объявления объектов, это такие функции. Примерно как тут https://cplusplus.com/doc/tutorial/classes/ , поищи там по слову oops
Чтобы вызвать шаблонный конструктор — надо ему как то указать шаблонный параметр. Прямого способа это сделать нет, но можно через аргумент, примерно так
Здесь уже упомянули, что частичная специализация для функций не поддерживается. Но в таких случая обычно не составляет особого труда перейти от специализаций к перегрузкам. Обрати внимание, использование остается именно таким, как в исходном примере, меняется только сама реализация полиморфизма. Примерно так:
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Прямой "короткий" ответ на вопрос не имеет никакого отношения ни к каким частичным специализациям функций. Язык просто запрещает объявление явных специализаций любых шаблонов внутри определения охватывающего шаблона класса. Этот запрет в одинаковой мере распространяется и на классы, и на функции, т.е. отсутствие частичной специализации функций тут вообще ни при чем.
Но при этом частичные специализации можно делать прямо в классе:
struct A
{
template <typename> struct Foo;
template <typename T> struct Foo<T*> {}; // OKtemplate <> struct Foo<int> {}; // error: explicit specialization in non-namespace scope 'struct A'
};
Это просто для полноты картины.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[10]: Специализация метода. Нужно устранить ошибку
Здравствуйте, vopl, Вы писали:
σ>>Предлагаю научиться
V>Тю.. Ты какой то обиженный что ли? Фу таким быть . Порицание .
Ты не понимаешь, это просто такой стиль — педагогический сарказм. У него есть все ответы, но он их нам не говорит. Чтоб мы думали, искали, развивались...
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, vopl, Вы писали:
V>Здравствуйте, SVV, Вы писали:
SVV>>как правильно написать специализацию метода?
V>Напрямую — никак. Это будет частичная специализация, язык такое не позволяет. Но, можно нечто похожее организовать через SFINAE или через концепты
... V>Еще можно вынести специализацию в другой класс и его уже специализировать, а foo оставить обобщенным..
А как подобное провернуть с конструктором? Проблема с вызовом такого конструктора:
template<typename T>
struct STest4
{
template<typename H> STest4() requires is_same_v<H, TypeH1> { cout << "ctor(TypeH1)" << endl; }
template<typename H> STest4() requires is_same_v<H, TypeH2> { cout << "ctor(TypeH2)" << endl; }
...
};
STest4<float> st5_1<TypeH1>();//warning C4930: 'STest4<float> st5_1(void)': prototyped function not called (was a variable definition intended?)
STest4<float> st5_2<TypeH2>();//warning C4930: 'STest4<float> st5_1(void)': prototyped function not called (was a variable definition intended?)
код компилируется, но конструктор не вызывается.
Re[4]: Специализация метода. Нужно устранить ошибку
Мне подходит. Спасибо.
Получается, что моя проблемы была в том, что я забыл про фигурные скобки и что нужно опредлить пустую Tag (... Tag{}; а не ... Tag; )
Я понимал, что вызов st5_1 выглядит как определение функции, но думал что, может, есть способ сказать компилятору, что это именно определения объектов. Нет так нет.
Re[2]: Специализация метода. Нужно устранить ошибку
Здравствуйте, σ, Вы писали:
V>>Напрямую — никак. Это будет частичная специализация, язык такое не позволяет.
σ>Как можно понять, что template<typename T> void STest4<T>::foo<TypeH2>() это частичная специализация?
Ну, понять это достаточно просто: если после подстановки аргументов шаблон воплощается в тип/значение — то это полная специализация, а если все еще остается шаблоном — то это частичная. В приведенном куске метод foo принадлежит наблону STest4<T>, то есть сам продолжает быть шаблоном, занчт — частичная специализация. Еще примеры:
V>>>Напрямую — никак. Это будет частичная специализация, язык такое не позволяет.
σ>>Как можно понять, что template<typename T> void STest4<T>::foo<TypeH2>() это частичная специализация?
V>Ну, понять это достаточно просто: если после подстановки аргументов шаблон воплощается в тип/значение — то это полная специализация, а если все еще остается шаблоном — то это частичная. В приведенном куске метод foo принадлежит наблону STest4<T>, то есть сам продолжает быть шаблоном, занчт — частичная специализация.
Здравствуйте, σ, Вы писали:
V>>>>Напрямую — никак. Это будет частичная специализация, язык такое не позволяет.
σ>>>Как можно понять, что template<typename T> void STest4<T>::foo<TypeH2>() это частичная специализация?
V>>Ну, понять это достаточно просто: если после подстановки аргументов шаблон воплощается в тип/значение — то это полная специализация, а если все еще остается шаблоном — то это частичная. В приведенном куске метод foo принадлежит наблону STest4<T>, то есть сам продолжает быть шаблоном, занчт — частичная специализация.
σ>Интересные методы, конечно. Я думал критерий это <TypeH2> после foo (http://eel.is/c++draft/temp.decls.general#2.sentence-3)
Оо.. Я чето от такой формулировки немного в ступоре ..
A partial specialization of a template provides an alternative definition of the template that is used instead of the primary definition when the arguments in a specialization match those given in the partial specialization.
Или простыми словами — из шаблона сделали чуть более специализированный шаблон.
An explicit specialization of ... can be declared by a declaration introduced by template<> ...
То есть, перечень шаблонных параметров пуст (следовательно все аргументы конкретны), то есть ничего шаблонного в нем не осталось и получилась уже нешаблонная инстанция — тип/значение/функция.
Re[6]: Специализация метода. Нужно устранить ошибку
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Прямой "короткий" ответ на вопрос не имеет никакого отношения ни к каким частичным специализациям функций. Язык просто запрещает объявление явных специализаций любых шаблонов внутри определения охватывающего шаблона класса. Этот запрет в одинаковой мере распространяется и на классы, и на функции, т.е. отсутствие частичной специализации функций тут вообще ни при чем.
Черт, точно!
АТ>(Я все время забываю, где этот запрет сформулирован в стандарте и навскидку не могу его найти.)
A partial specialization of a template provides an alternative definition of the template
σ>Тут говорится что partial specialization делает, а не что это такое.
Ага. Определение частичной специализации судя по всему вот это σ> Интересные методы, конечно. Я думал критерий это <TypeH2> после foo (http://eel.is/c++draft/temp.decls.general#2.sentence-3)
Но, мне данное определение что то не ложится в голову. Может кто из гуру пояснит что тут как понимать ..
Re[7]: Специализация метода. Нужно устранить ошибку
the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well
>> *смотрит на explicit specialization в class scope* >> *кидает параграф про "an explicit specialization ... that appears in namespace scope"*
σ>
Предлагаю не придираться к словам и чуть включать эмпатию, мы тут не машины, все можем не вполне четко высказываться и не вполне четко друг друга понимать. Я отвечал на этот кусок:
АТ>(Я все время забываю, где этот запрет сформулирован в стандарте и навскидку не могу его найти.) АТ>Явные специализации шаблонов-членов должны объявляться в namespace scope и должны делаться только для конкретных специализаций охватывающего шаблона. То есть, подчеркиваю, это ограничение в равное мере распространяется и на вложенные шаблоны классов, то есть отсутствие частичной специализации функций тут вообще ни при чем. АТ>
АТ>template <typename T> struct S
АТ>{
АТ> template <typename U> struct N {};
АТ>};
АТ>template <> template <> struct S<int>::N<double> {}; // <- Так можно
АТ>template <typename T> template <> struct S<T>::N<double> {}; // <- А вот так нельзя
АТ>
Re[8]: Специализация метода. Нужно устранить ошибку
Предлагаю научиться пользоваться цитированием, т.к. было написано АТ>>(Я все время забываю, где этот запрет сформулирован в стандарте и навскидку не могу его найти.) V>Похоже это тут https://eel.is/c++draft/temp.expl.spec#17.sentence-1
Где АТ>>(Я все время забываю, где этот запрет сформулирован в стандарте и навскидку не могу его найти.)
относится к
Здравствуйте, σ, Вы писали:
АТ>>Прямой "короткий" ответ на вопрос не имеет никакого отношения ни к каким частичным специализациям функций. Язык просто запрещает объявление явных специализаций любых шаблонов внутри определения охватывающего шаблона класса. Этот запрет в одинаковой мере распространяется и на классы, и на функции, т.е. отсутствие частичной специализации функций тут вообще ни при чем.
σ>Кхм. Ващет, вопрос был про template<typename T> void STest4<T>::foo<TypeH2>() { ... } (вне класса), а не про template<> void foo<TypeH1> (внутри класса)
АТ>>
АТ>>(Я все время забываю, где этот запрет сформулирован в стандарте и навскидку не могу его найти.)
σ>Неудивительно, его больше 5 лет как нет: https://cplusplus.github.io/CWG/issues/727.html σ>И запрет выпилили в статусе defect report-а, т.е. с ретроактивным применением выпиливания.
Ах вот оно что! Я просто пошел на поводу у GCC, который до сих пор выдает ошибку. (Clang с версии 7 не страдает этой проблемой.)
В поисках по стандарту я как раз таки нашел вот это самое http://eel.is/c++draft/temp.expl.spec#3
> 3 An explicit specialization may be declared in any scope in which the corresponding primary template may be defined (9.8.2.3, 11.4, 13.7.3).
Но это как будто снимает запрет и для функций тоже. Тот же самый Clang молча проглатывает и
Здравствуйте, σ, Вы писали:
АТ>>Прямой "короткий" ответ на вопрос не имеет никакого отношения ни к каким частичным специализациям функций. Язык просто запрещает объявление явных специализаций любых шаблонов внутри определения охватывающего шаблона класса. Этот запрет в одинаковой мере распространяется и на классы, и на функции, т.е. отсутствие частичной специализации функций тут вообще ни при чем.
σ>Кхм. Ващет, вопрос был про template<typename T> void STest4<T>::foo<TypeH2>() { ... } (вне класса), а не про template<> void foo<TypeH1> (внутри класса)
Я посмотрел на комментарий `// ключевой момент`, который располагается внутри класса, и натуральным образом предположил, что речь идет именно об этом.
Best regards,
Андрей Тарасевич
Re[5]: Специализация метода. Нужно устранить ошибку
SVV>Я понимал, что вызов st5_1 выглядит как определение функции, но думал что, может, есть способ сказать компилятору, что это именно определения объектов. Нет так нет.
Способа два: либо через фигурные скобки, либо через двойные обычные.