Использование объявления для имени шаблона - программирование
Подтвердить что ты не робот

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

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

4b9b3361

Ответ 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?