[英]C++ using declaration with typename in inheriting-constructors
在閱讀這個問題時 ,我發現了一個奇怪的觀點:
template <typename T>
class Subclass : public Baseclass<T>
{
public:
using typename Baseclass<T>::Baseclass;
// ^^^^^^^^
};
由於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;
};
為了確保,我寫了一個測試代碼。
#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");
}
但是,它運行在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 *)
它也沒有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 *)
為什么我得到這些結果? 我錯過了什么?
標准非常明確([namespace.udecl] / 1)
using聲明:
使用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
抱怨malplaced typename
關鍵字。 但是,這甚至不一致,因為它應該在using Base< T >::Ttype;
抱怨缺少typename
using Base< T >::Ttype;
。 這顯然是一個鏗鏘的錯誤。
編輯如果基類不是模板類,也允許使用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++
};
對不起,為什么要using
,為什么不只是typedef
?
template <typename T>
class Sub : public Base<T>
{
typedef Base<T> Base;
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.