簡體   English   中英

C ++在繼承構造函數中使用帶有typename的聲明

[英]C++ using declaration with typename in inheriting-constructors

在閱讀這個問題時 ,我發現了一個奇怪的觀點:

template <typename T>
class Subclass : public Baseclass<T>
{
public:
    using typename Baseclass<T>::Baseclass;
    //    ^^^^^^^^
};

由於typenameBaseclass<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;
};

SubNoTypenameSubTypename都被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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM