Использование объявления для имени шаблона

Когда 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 вообще.

Ответы

Ответ 1

Следующее прекрасно работает с С++ 11:

#include <iostream>

template< typename d >
struct base {
    template< typename >
    struct ct {};

    template< typename >
    void ft() {std::cerr << "cheesecake" << std::endl;}
};

template< typename x >
struct derived : base< derived< x > > {
  template<typename X>
    using ct = typename derived::base::template ct<X>; // new in C++11
  using derived::base::ft;
};

int main()
{
  derived<int>::ct<float> c;
  derived<int> a;
  a.ft<int>();
}

Если это не то, что вы хотели, можете ли вы привести пример того, как вы хотели бы использовать ct и ft?