12

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.

Alex Chamberlain
  • 4,147
  • 2
  • 22
  • 49
Trevor Robinson
  • 15,694
  • 5
  • 73
  • 72
  • Post some code that should compile (in your opinion) for conforming compilers, but doesn't. And post how you are using the template. –  Jul 01 '09 at 20:21
  • I believe all relevant information is above. Versions 1-4 work on MSVC 9, which has non-conforming one-stage name resolution (i.e. at instantiation time). Only versions 2 & 3 work on GCC 4.3. I don't know any reason Version 4 should be invalid, but GCC won't accept it. As for usage, it doesn't really matter how this is instantiated. I'm just trying to get the template declaration to compile. The code above is a simplification of a much more complex container adapter. – Trevor Robinson Jul 01 '09 at 20:57
  • When posting code here, don't expect people to have to edit it to get it to compile. –  Jul 01 '09 at 21:25
  • 2
    Sorry, it just seemed more readable the way it is, rather than repeating both class definitions 4 times. In general, I agree with you, but this just involves deleting a block of contiguous lines. – Trevor Robinson Jul 01 '09 at 23:37

2 Answers2

10

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!

Trevor Robinson
  • 15,694
  • 5
  • 73
  • 72
  • 1
    This is a bug, but only relatively recently, so I think you shouldn't be too hard on gcc. The following core issue highlights the wording change "http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#11". This went in to the C++ '03 standard. – Richard Corden Jul 02 '09 at 10:03
  • Thanks, Richard, that's the exact link I was looking for! – Trevor Robinson Jul 02 '09 at 17:42
-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.

Stephen C. Steel
  • 4,380
  • 1
  • 20
  • 21
  • 5
    He's defined his Base/Derived types as structs, so their members are *public* by default, not private. – luke Jul 01 '09 at 20:24