6

In this question, the asker has the following function:

template<typename ITER>
bool nextPermutation(ITER start, ITER end)
{
    return nextPermutation(start, end, std::iterator_traits<ITER>::iterator_category());
}

Why isn't a typename needed before the std::iterator_traits? I thought it was needed for nested types of a template, if the template is dependent on a template parameter itself? GCC seems to support my idea, as it doesn't compile under both 4.3.4 and 4.5.1, demanding a typename. Even so, it still compiles just fine under both Visual Studio 2008 and 2010.
Is this just another Visual Studio extension/bug I don't know about?
Or is it actually possible to deduce that iterator_category is either a type or a function because it's followed by a pair of parenthesis ()? (See @DeadGM's messages starting here.) So is this maybe actually a bug in GCC?

Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • In addition to the options you list (constructor and function), `iterator_category` could be a static member variable of a type that defines operator(). – Sjoerd Apr 15 '11 at 23:24
  • @Sjoerd: Or a function pointer. – sbi Apr 15 '11 at 23:25

2 Answers2

12

Visual C++ is well-known not to (fully) support two-phase lookup, which is the underlying reason for why typename is required in the first place. If the compiler doesn't fully support this, it might not fully parse a template before it is instantiated, by which time it "knows" that std::iterator_traits<ITER>::iterator_category is a type. Obviously, this deficiency extends to VC10.

When it comes to typename, I'd trust GCC over VC any day.

Community
  • 1
  • 1
sbi
  • 219,715
  • 46
  • 258
  • 445
  • Perfectly complete answer, but I'm gonna take @Johannes' answer, as it explains a bit more on the late parsing thing. +1 though. :) – Xeo Apr 19 '11 at 20:19
6

Doesn't MSVC implement the late-parsing scheme? In such a scheme, the compiler isn't dependent on typename. It just stores all the token in between the template definition's braces, and when the template is instantiated, it parses those tokens. Since it then knows what is and what is not a type, it will work without typename.

But if the compiler doesn't diagnose the missing typename when you instantiate the template, then it's non-conforming.

Or is it actually possible to deduce that iterator_category is either a type or a function because it's followed by a pair of parenthesis ()?

All that matters is whether the name is dependent and qualified. Whether or not the template could deduce itself that the name is always a type doesn't matter. It might matter for the quality of error messages for missing typenames though.

FWIW, no it's not possible to deduce anything about iterator_category on a language level.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • Note that the required diagnose is allowed to be just a warning. So as long as the compiler issues at least one warning, it is allowed to "compile just fine." Secondly, that warning could be turned off by default - all compilers I know require a flag or option to be present in order to follow the C++ standard as closely as possible: When upgrading a compiler, most customers don't want new warnings/errors for their old code, so backwards compatibility forces compiler writers to hide new errors behind additional options. – Sjoerd Apr 15 '11 at 23:33
  • @Sjoerd: The standard always only ever speaks of "diagnostics". That could be errors or warnings, either would be fine. – sbi Apr 15 '11 at 23:44
  • @sbi I'm sure you and Johannes know that, but it's not common knowledge. – Sjoerd Apr 15 '11 at 23:46