7

Это вопрос this. Я специально интересовался, если частичной специализации класса члена как это:Является ли законным выполнять частичную внутриклассическую специализацию класса шаблона-члена в производном классе

struct FooParent { 
    template <class> 
    struct Bar{ }; 
}; 

struct Foo: FooParent { 
    template <class T> 
    struct Bar<T*> {}; 
}; 

Я знаю, это может быть сделано внутри области видимости пространства имен:

template <class T> 
struct Foo::Bar<T*>{ }; 

Но я также специально заинтересован в в классе частичная специализация на уровне производного класса.

Оба лязг и GCC жалуется, когда встреча бывший:

лязг утверждает, что существует явная специализация шаблона, который, очевидно, не происходит:

error: explicit specialization of 'Bar' in class scope

НКУ немного менее многословным здесь и говорит что специализация шаблона члена должна выполняться в области пространства имен, которая, очевидно, не относится к не производному классу.

error: specialization of 'template struct FooParent::Bar' must appear at namespace scope

Это gcc прямо здесь, в сообщении об ошибке?

+0

Я думаю, [это] (http://eel.is/c++draft/temp.class.spec#5) правила на нем. Вы не можете определить первичный шаблон в производном классе, так что вы также не можете объявить частичную специализацию. - Частичная специализация шаблона шаблона класса может быть объявлена ​​или переопределена в любой области пространства имен, в которой может быть определен соответствующий первичный шаблон_ – skypjack

+0

@skypjack не так, как это есть **, позволяя ** специализацию области нежелательного пространства имен, не отказываясь от чего-либо - см. [справочный вопрос] (http://stackoverflow.com/questions/40656857/why-is-in-class-partial-specialization-well-formed) и обсуждение в комментариях ... –

+0

Я понял, что это разрешено, таким образом все остальное запрещено. Вы говорите вместо этого, что это разрешено, но может быть что-то еще объявленное как разрешенное где-то в стандарте, верно? Поэтому вы хотите, чтобы явное правило запрещало это. Я правильно понял вашу цель? – skypjack

ответ

1

Я пытаюсь подвести итог тому, что я сказал в комментариях к вопросу, по просьбе ОП.


Я думаю, [temp.class.spec]/5 достаточно, чтобы ответить на вопрос.
В частности:

A class template partial specialization may be declared or redeclared in any namespace scope in which the corresponding primary template may be defined [...].

В этом случае, что на самом деле править на ней, где основной шаблон может быть определен.
В этом примере вы пытаетесь объявить (и контекстно определить, но это прежде всего объявление) частичную специализацию в производном классе.

Короткий ответ: вы не можете определить основной шаблон в производном классе, поэтому вы также не можете объявить частичную специализацию в этом классе.

Если бы это было возможно, следующее было бы возможно тоже:

struct FooParent { 
    template <class> 
    struct Bar; 
}; 

struct Foo: FooParent { 
    template <class T> 
    struct FooParent::Bar<T*> {}; 
}; 

Или это один, если вы предпочитаете:

struct Foo: FooParent { 
    template <class T> 
    struct Bar<T*> {}; 
}; 

К сожалению, они не имеют права, и это было бы достаточно (?) что ваша попытка специализировать шаблон шаблона также недействительна.

В любом случае, давайте рассмотрим это немного дальше.
Основной шаблон является частью спецификации элемента Foo (см. here для получения дополнительной информации).
Таким образом, вопрос - Где я могу определить такой шаблон?, быстро становится - Где я могу определить любого другого члена класса?.
Опять же, ответ - не относится к производному классу.


Я уверен, что адвокат языка даст вам более прямое и прямое объяснение.
Я также уверен, что тот же самый адвокат языка будет проклинать меня за то, что упомянул неправильные разделы стандарта.
В любом случае, я надеюсь, что несколько примеров, приведенных выше, могут дать вам базовую точку, с которой можно начать.

+0

'template struct Foo :: Bar {};' этот фактически принимается компиляторами - не в области производного класса, а в области пространства имен, где был объявлен базовый класс, - это также было введено в заблуждение мне кажется, что это должно быть возможно ... Я действительно думаю, что синтаксис должен быть запрещен компиляторами ... –

+0

@WF Почему это должно быть запрещено? Это тот же синтаксис, который вы можете использовать для определения члена вне линии. И вложенный шаблон класса является членом класса, как указано в ответе. – skypjack

+0

Потому что, когда, например, вы объявляете 'Goo', исходя из' FooBase', и вы специализируетесь на 'Goo :: Bar ' вы специалист по редекларированию ... Что, если 'FooBase' был шаблоном, он просто вызывает путаницу и неожиданное поведение ... –