Ответ 1
Стандарт довольно ясен об этом ([namespace.udecl]/1)
с помощью декларирование:
с использованием typename_opt nested-name-specifier unqualified-id;
Ключевое слово typename
поэтому является необязательной частью объявления using, которое может появляться даже для использования объявлений не-типов. Поэтому следующий код должен быть стандартным:
template < typename T > class Base {
protected:
typedef T Ttype;
Ttype member;
public:
Base() {
std::cout << "A::A()\n";
}
Base(int) {
std::cout << "A::A(int)\n";
}
Base(const char *) {
std::cout << "A::A(const char *)\n";
}
protected:
void memfunc(void) {
std::cout << "A::memfunc(void)\n";
}
};
template< typename T >
struct SubNoTypename : protected Base< T > {
using Base< T >::Base;
using Base< T >::member;
using Base< T >::memfunc;
using Base< T >::Ttype; // n.b. no error in clang++
};
template< typename T >
struct SubTypename : protected Base< T > {
using typename Base< T >::Base; // error in clang++
using typename Base< T >::member; // error in clang++
using typename Base< T >::memfunc; // error in clang++
using typename Base< T >::Ttype;
};
Оба SubNoTypename
и SubTypename
распознаются как стандартное соответствие gcc. С другой стороны, clang++ жалуется на SubTypename
на неприменимые ключевые слова typename
. Однако это даже не согласовано, потому что тогда оно должно жаловаться на отсутствие typename
в using Base< T >::Ttype;
. Это явно ошибка clang.
Edit
Ключевое слово typename
также допускается, если базовый класс не является классом шаблонов, местом, где обычно вы никогда не ожидали бы, что это ключевое слово будет действительным:
class BaseNoTemplate {
protected:
typedef T Ttype;
Ttype member;
public:
BaseNoTemplate() {
std::cout << "A::A()\n";
}
BaseNoTemplate(const char *) {
std::cout << "A::A(const char *)\n";
}
void memfunc(void) {
std::cout << "A::memfunc(void)\n";
}
};
struct SubNoTemplateNoTypename : protected BaseNoTemplate {
using BaseNoTemplate::BaseNoTemplate;
using BaseNoTemplate::member;
using BaseNoTemplate::memfunc;
using BaseNoTemplate::Ttype;
};
struct SubNoTemplateTypename : protected BaseNoTemplate {
using typename BaseNoTemplate::BaseNoTemplate; // error in clang++
using typename BaseNoTemplate::member; // error in clang++
using typename BaseNoTemplate::memfunc; // error in clang++
using typename BaseNoTemplate::Ttype; // n.b. no error in clang++
};