1

Consider the following code, which compiles fine in clang but not in gcc (4.7.2):

template<typename T> using remove_ref_typed =
    typename std::remove_reference<T>::type; // alias-template w/ 'typename'

template<typename T> using remove_ref =
    std::remove_reference<T>; // alias-template w/o 'typename'

enum class E : int { E0, E1 }; // some enum class

class C {} obj; // some non-enum class

void proof_of_concept()
{
    remove_ref<C&>::type o1 = obj; // ... gcc ok
    remove_ref_typed<C&> o2 = obj; // ... gcc ok

    remove_ref<E&>::type e1 = E::E1; // ... gcc ok
    remove_ref_typed<E&> e2 = E::E1; // ... gcc internal "bus error"
}

The code compiles fine in clang, but in gcc (4.7.2) the final statement results in:

sandbox_cpp11.cpp:100:22: internal compiler error: Bus error
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.

The difference between the problematic statement and the previous 3 statements is:

  1. It involves an enum class type, instead of non-enum class type.
  2. It uses an alias-template which declares typename and ::type for convenience

My question: Does use of typename in this way (in an "alias template") comply with the C++11 standard even if used in a context in which the typename specifier wouldn't otherwise be necessary? Or is this a "language non-compliance bug" in gcc?

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
etherice
  • 1,761
  • 15
  • 25
  • 7
    "internal compiler error" is always a bug, no questions asked. And `typename` is ignored if not needed in using-aliases. – Xeo Apr 01 '13 at 23:21
  • 2
    It is definitely a bug. Btw, [GCC 4.8.0 compiles it](http://liveworkspace.org/code/48Ihhx$248) – Andy Prowl Apr 01 '13 at 23:21
  • @Xeo: Btw is it really "not needed" here? – Andy Prowl Apr 01 '13 at 23:22
  • @Xeo: Yes :) which is why I specified "non-compliance bug", as opposed to crashing instead of dumping a useful error message (which would be a much less critical bug). – etherice Apr 01 '13 at 23:27
  • @etherice: But why is it not needed? You can't just remove `typename` from `remove_ref_typed`, that would be ill-formed – Andy Prowl Apr 01 '13 at 23:28
  • @AndyProwl: Ahhh, and I see gcc 4.8.0 is "stable" now (as of last week). This bug must have been identified in 4.7... I'll go ahead and upgrade. If someone could provide a link to bug report that would be appreciated. – etherice Apr 01 '13 at 23:28
  • @AndyProwl: Notice how it's not needed in the previous statements (the ones using `remove_ref` instead of `remove_ref_typed`)... This is because the template-parameter (E& and C&) are known-types, and not template types, so the compiler does not need the `typename` specifier to know if symbols coming after the scope-resolution operator are types or not. And according to Xeo, the language explicitly states that `typename` should be ignored by the compiler when instantiation of a `using` alias-template results in unnecessary use of the `typename` specifier. – etherice Apr 01 '13 at 23:34
  • @etherice: That's a different situation: `remove_ref` doesn't need `typename` because it doesn't use a qualified, dependent name. `remove_ref_typed` does. I don't believe any compiler would accept `remove_ref_typed` without the `typename` keyword. – Andy Prowl Apr 01 '13 at 23:36
  • 2
    @AndyProwl: I see what you're asking. Yes, the `typename` specifier is needed in `remove_ref_typed` for dependent name `::type`. The disconnect here is that Xeo and I were referring to the **instantiation** of that alias template. When it's instantiated with a **known** type (as opposed to a **template** type) the `typename` specifier is unnecessary. Normally, when the `typename` specifier is used unnecessarily, the compiler complains, but it is allowed (ignored) w/o warning when the result of instantiating an alias template. – etherice Apr 01 '13 at 23:45
  • @AndyProwl: To be clear, I always assumed it was just ignored when used in this context. But I questioned this assumption today (hence this question) when gcc choked on the example code provided in the "question". I wanted to make sure it was in fact a gcc bug, and not something that was technically ill-formed w.r.t. the language. – etherice Apr 01 '13 at 23:49
  • 1
    @etherice: OK, clear :) – Andy Prowl Apr 01 '13 at 23:50
  • The existence of some context where a template is instantiated with an explicit name does not mean that dependent types do not need `typename` -- parsing of the `using` directive itself, before any instantiation, uses the `typename`. – Yakk - Adam Nevraumont Apr 02 '13 at 03:07

0 Answers0