3
template<class T>
void foo()
{
    M
}

Unless I instantiate it, Visual C++ does not tell me the above code contains error(s). Why is this?

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
user541686
  • 205,094
  • 128
  • 528
  • 886

2 Answers2

9

Because Visual C++ is in error. It doesn't implement two-phase lookup. It's supposed to check the template for proper syntax even if you don't instantiate it, but it doesn't do that.

GCC doesn't accept it. Not saying that necessarily means it's not right, but there's an example for you anyway of what's supposed to happen.

Community
  • 1
  • 1
Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • Two-phase lookup shouldn't change the fact that the body needs to be syntactically valid. – Puppy Jul 21 '12 at 05:54
  • @DeadMG: Why do you say that? If a template is not instantiated, two-phase lookup becomes one-phase lookup. If a template is not instantiated *and* two-phase lookup is not implemented, it becomes zero-phase lookup. In other words, the template is not looked at. Is this not what happens? (I don't have Visual C++, so I can't test the extents of exactly what it will allow) – Benjamin Lindley Jul 21 '12 at 05:58
  • Well, for one, how can you know when the template ends if you don't parse it? – Puppy Jul 21 '12 at 05:59
  • @DeadMG: Obviously it has to parse it to some extent, but that doesn't mean it can't be very lax in what it enforces. – Benjamin Lindley Jul 21 '12 at 06:00
  • @DeadMG: I may be using the word syntax wrong, I didn't do a computer science degree and never really studied compilers and parsing too closely like a CS student usually does. – Benjamin Lindley Jul 21 '12 at 06:11
  • @BenjaminLindley: I've not CS degree either, but that doesn't mean a CS student knows all these, not at least in Indian Universities. – Nawaz Jul 21 '12 at 06:19
7

The C++ Standard contains an informal description of this matter which describes what I think would be a good guideline and is taken by many people to be the normative requirement implied by the specification.

However, implementations can point to normative parts of the Standard that allow them to go further than what the "obvious" rules seem to state. I will describe this below.

Non-Normative description

The Standard allows an implementation not to check template definitions until they are instantiated. It doesn't give a formal description as to when a "template definition" is actually supposed to be a template definition, but the usual implementation is to do forms of "brace balancing" / "parens balancing": Start from the outermost brace of the definition's body, count until you hit the last closing brace. Everything in between is ignored.

I suppose an example from the Standard clarifies this further

template<class T> class X {
  // ... (omitted) ...
  void g(T t) {
    +; // may be diagnosed even if X::g is not instantiated
  }
};

So early diagnosis of syntax or semantic errors in template definitions is a "quality of implementations".


Normative description

These rules are of the quality "no diagnostic required". Noteworthy, implementations by these rule are granted the license not to diagnose ill-formed template definitions even if the template is instantiated, despite what the non-normative note of the Standard says. If any rule for which no diagnostic is required is violated, an implementation is free to do whatever it wants with the entire program.

It should be noted that also, there is no syntactically ill-formed "template definition", because this very term is defined by the syntax itself. A lonely + renders the whole enclosing context to be some soup of nonsensical tokens.

Last but not least, the committee knows about these "loopholes", but there was no majority to change this so far, as far as I know.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212