Невозможно импортировать typedefs из базового класса шаблона - PullRequest
0 голосов
/ 06 ноября 2018

Этот вопрос не является дубликатом, но является следствием Распространение 'typedef' от основанного до производного класса для 'template'

В качестве решения для наследования typedefs было предложено использовать using для импорта их в производный класс, тогда как простого using typename Base::typedefed_type должно быть достаточно.

Следующий код в основном взят из Ответ Романа Круглова :

#include <vector>
template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
public:
    using typename A::Vec_t;
    // .........

private:
    Vec_t v;
};

int main()
{
B<int> bb;
}

Однако он не компилируется, потому что компиляторы очень хотят, чтобы аргументы шаблона были A.

Сообщение об ошибке компилятора Intel:

    1>C:\Work\EDPS\test_eigen\test_eigen.cpp(27): error : argument list for class template "A" is missing
1>      using typename A::Vec_t;
1>                     ^
1>          detected during instantiation of class "B<T> [with T=int]" at line 34
1>
1>C:\Work\EDPS\test_eigen\test_eigen.cpp(31): error : identifier "Vec_t" is undefined
1>      Vec_t v;
1>      ^
1>          detected during instantiation of class "B<T> [with T=int]" at line 34
1>

MVC Сообщение об ошибке:

 c:\work\edps\test_eigen\test_eigen.cpp(27): error C2955: 'A': use of class template requires template argument list
1>c:\work\edps\test_eigen\test_eigen.cpp(17): note: see declaration of 'A'
1>c:\work\edps\test_eigen\test_eigen.cpp(32): note: see reference to class template instantiation 'B<T>' being compiled
1>c:\work\edps\test_eigen\test_eigen.cpp(27): error C3210: 'A': a member using-declaration can only be applied to a base class member
1>c:\work\edps\test_eigen\test_eigen.cpp(32): warning C4624: 'B<int>': destructor was implicitly defined as deleted

Так что не так? Я что-то пропустил? Или, возможно, комментарии и ответы там неправильные ??

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Я думаю, что путаница возникает из-за того, что A используется в качестве базового класса. Если шаблон класса является производным от шаблона класса с аргументом шаблона, необходимо полностью указать имя базового класса. Но если класс является производным от специализации шаблона класса, вы можете использовать имя базового класса без списка аргументов шаблона.

template<typename T>
struct A {
    using t = T;
};

template<typename T>
struct B : A<T> {
    using typename A<T>::t; // Full qualification needed -> mandatory argument list
};

struct C : A<int> {
    using typename A::t; // Injected class name -> optional argument list
};

Live on Coliru

Также обратите внимание, что t доступен в C напрямую, без использования объявлений или typedef. Я все еще могу быть полезен, например, если C наследуется от A<int> в частном порядке, но вы хотите, чтобы t был публично доступен в C (в этом примере C наследуется публично по умолчанию, потому что это struct).

0 голосов
/ 06 ноября 2018

Просто измените это как

template<typename T>
class B : public A<T>
{
public:
    using typename A<T>::Vec_t;
    // .........

};

В C ++, если A является шаблоном, автономный A не является «завершенным» типом. Вам необходимо указать аргумент шаблона. Вот почему A<T> решает это.

...