Когда CRTP используется внутри шаблона (или, как правило, когда параметр шаблона передается как аргумент шаблона базового класса), невозможно ли назвать шаблоны базовых элементов в объявлении using
?
template< typename d >
struct base {
template< typename >
struct ct {};
template< typename >
void ft() {}
};
template< typename x >
struct derived : base< derived< x > > {
using derived::base::template ct; // doesn't work
using derived::base::ft; // works but can't be used in a template-id
};
Мне кажется, что это дыра в языке, просто потому, что в грамматическом производстве с использованием-декларации нет идентификатора с квалификацией.
using-declaration:
using typename(opt) nested-name-specifier unqualified-id ; // have this
using :: unqualified-id ;
unqualified-id:
identifier
operator-function-id
conversion-function-id
literal-operator-id
~ class-name
~ decltype-specifier
template-id
qualified-id:
nested-name-specifier template(opt) unqualified-id // want this
:: identifier
:: operator-function-id
:: literal-operator-id
:: template-id
Если единственным правилом было using-declaration: using typename(opt) qualified-id
, то единственными последствиями были бы
- исключая
:: conversion-function-id
,:: ~ class-name
и:: ~ decltype-specifier template-id
, которые не имеют смыслового смысла, - разрешающий
:: template-id
, который уже явно запрещен 7.3.3/5, и - позволяет ключевому слову
template
, которое уже имеет достаточную спецификацию для исправления дыры.
Правильно ли этот анализ?
Учитывая, что новая грамматика разрешена, возможно, объявление с typename
должно импортировать шаблон шаблона или шаблон псевдонима, а один без typename
должен импортировать шаблон функции или переменной в текущую область.
using typename derived::base::template ct;
using derived::base::ft;
Для этого может потребоваться дополнительная спецификация. Кроме того, текущий статус-кво, похоже, состоит в том, что зависимые имена шаблонов всегда имеют неоднозначный вид (а не шаблон-идентификаторы), поэтому неясно, что typename
принадлежит ct
вообще.