ikh*_*ikh 13 c++ typename using-declaration language-lawyer inheriting-constructors
在阅读这个问题时,我发现了一个奇怪的观点:
template <typename T>
class Subclass : public Baseclass<T>
{
public:
using typename Baseclass<T>::Baseclass;
// ^^^^^^^^
};
Run Code Online (Sandbox Code Playgroud)
既然typename,Baseclass<T>::Baseclass应该注入类名,而不是构造函数.据我所知,情况与此相同:
template <typename T>
class Base
{
public:
typedef short some_type;
};
template <typename T>
class Sub : public Base<T>
{
public:
using typename Base<T>::some_type;
};
Run Code Online (Sandbox Code Playgroud)
为了确保,我写了一个测试代码.
#include <iostream>
template <typename T>
class Base
{
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"; }
};
template <typename T>
class Sub : public Base<T>
{
using typename Base<T>::Base;
};
int main()
{
Sub<char> s1;
Sub<char> s2(3);
Sub<char> s3("asdf");
}
Run Code Online (Sandbox Code Playgroud)
但是,它运行在gcc 4.8.3上.
$ g++ -std=c++1y -Wall -Wextra -Werror -pedantic test.cpp -o test && ./test
A::A()
A::A(int)
A::A(const char *)
Run Code Online (Sandbox Code Playgroud)
它也没有运行typename.
$ cat test.cpp
...
using Base<T>::Base;
...
$ g++ -std=c++1y -Wall -Wextra -Werror -pedantic test.cpp -o test && ./test
A::A()
A::A(int)
A::A(const char *)
Run Code Online (Sandbox Code Playgroud)
为什么我得到这些结果?我错过了什么?
标准对此非常清楚([namespace.udecl]/1)
使用声明:
使用 typename_opt 嵌套名称说明符 unqualified-id ;
因此,关键字typename是using 声明的可选部分,甚至对于非类型的 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;
};
Run Code Online (Sandbox Code Playgroud)
SubNoTypename和均被SubTypenamegcc 视为符合标准。另一方面,clang++ 抱怨关键字SubTypename放置不当typename。然而,这甚至不一致,因为它应该抱怨typename中的缺失using Base< T >::Ttype;。这显然是一个 clang bug。
编辑如果基类不是模板类,也允许使用
该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++
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
857 次 |
| 最近记录: |