Accessing types from dependent base classes

2020-08-13 08:10发布

问题:

Does anyone know why using-declarations don't seem to work for importing type names from dependent base classes? They work for member variables and functions, but at least in GCC 4.3, they seem to be ignored for types.

template <class T>
struct Base
{
  typedef T value_type;
};

template <class T>
struct Derived : Base<T>
{
  // Version 1: error on conforming compilers
  value_type get();

  // Version 2: OK, but unwieldy for repeated references
  typename Base<T>::value_type get();

  // Version 3: OK, but unwieldy for many types or deep inheritance
  typedef typename Base<T>::value_type value_type;
  value_type get();

  // Version 4: why doesn't this work?
  using typename Base<T>::value_type;
  value_type get(); // GCC: `value_type' is not a type
};

I have a base class with a set of allocator-style typedefs that I'd like to inherit throughout several levels of inheritance. The best solution I've found so far is Version 3 above, but I'm curious why Version 4 doesn't seem to work. GCC accepts the using-declaration, but seems to ignore it.

I've checked the C++ Standard, C++ Prog. Lang. 3rd ed. [Stroustrup], and C++ Templates [Vandevoorde, Josuttis], but none seem to address whether using-declarations can be applied to dependent base class types.

In case it helps to see another example, here is the same question being asked, but not really answered, on the GCC mailing list. The asker indicates that he has seen 'using typename' elsewhere, but that GCC doesn't seem to support it. I don't have another conforming compiler available to test it.

回答1:

As Richard Corden points out, this issue was addressed in the C++ Standard Core Language Defect Reports after the 2003 standard was ratified: How do the keywords typename/template interact with using-declarations?

Proposed resolution (April 2003, revised October 2003):

Add a new paragraph to the bottom of 7.3.3 [namespace.udecl]:

If a using-declaration uses the keyword typename and specifies a dependent name (14.7.2 [temp.dep]), the name introduced by the using-declaration is treated as a typedef-name (7.1.3 [dcl.typedef]).

This text doesn't seem to appear in the Second Edition standard from October 15, 2003.

GCC does not yet implement this resolution, as explained in bug 14258:

------- Comment #3 From Giovanni Bajo 2004-02-27 12:47 [reply] ------- The problem is that our USING_DECL doesn't record the "typename", that is the fact that it is a type which is imported through it. This used to work thanks to the implicit type name extension, I believe.

Duplicate bug 21484 indicates that 'using typename' works on Comeau and Intel compilers. Because MSVC treats all names as dependent, the construct is unnecessary (but permitted) for that compiler.


Fixed in GCC 4.7 on Dec 13 2011!



回答2:

You didn't include an access specifier (public/protected/private) in the template for Base before declaring the typedef for Base::value_type. As a result, it defaults to private and is not accessible in classes derived from Base.