1

From the book - C++ Templates: The Complete Guide by David, Nicolai

Thus, templates are compiled twice:

  1. Without instantiation, the template code itself is checked for correct syntax. Syntax errors are discovered, such as missing semicolons.
  2. At the time of instantiation, the template code is checked to ensure that all calls are valid. Invalid calls are discovered, such as unsupported function calls.

Keeping the first point, I wrote -

template<typename T>
void foo( T x)
{
   some illegal text
}

int main()
{
   return 0;
}

It build fine on Visual Studio 2010 with out any warnings with optimizations turned off. How ever, it failed on gcc-4.3.4. Which one is complying to the C++ standard ? Is it mandatory for template code to get compiled even with out template instantiation ?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Mahesh
  • 34,573
  • 20
  • 89
  • 115
  • 1
    VC++ does not implement two-phase name lookup. Never has, probably won't for a _long_ time (if ever). – ildjarn Apr 25 '12 at 21:22
  • I'm glad they erred on the side of leniency though. – Seth Carnegie Apr 25 '12 at 21:24
  • @Seth : I'm not -- it makes writing cross-platform code more difficult because there will be errors you don't see until you compile your code with a more compliant compiler. – ildjarn Apr 26 '12 at 03:33
  • @ildjarn only if you don't instantiate a template ever. And besides... just test it on a more compliant compiler. – Seth Carnegie Apr 26 '12 at 03:59
  • @Seth : No, there are other side-effects of this such as dependent types not being recognized as such, thus VC++ lets you get away with a lot of missing `template` and `typename` keywords that compliant compilers don't. And testing on a more compliant compiler is certainly impractical (Clang on Windows isn't pretty yet), albeit necessary for the time being. – ildjarn Apr 26 '12 at 04:15
  • @ildjarn ah, I see. Well there is GCC via MingW which I would guess is more compliant. – Seth Carnegie Apr 26 '12 at 04:42
  • Two-phase name lookup was added to VC++ 2017 (and later). Need to add the `/permissive-` compilation option. Source: https://devblogs.microsoft.com/cppblog/two-phase-name-lookup-support-comes-to-msvc/ – Ivan Kolev Nov 24 '21 at 09:21

2 Answers2

7

The program in question is ill-formed, but the C++ standard does not require a diagnostic in this case, so both Visual Studio and GCC are behaving in a compliant fashion. From §14.6/7 of the C++03 standard (emphasis mine):

Knowing which names are type names allows the syntax of every template definition to be checked. No diagnostic shall be issued for a template definition for which a valid specialization can be generated. If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required. If a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is done, and if the completeness of that type affects whether or not the program is well-formed or affects the semantics of the program, the program is ill-formed; no diagnostic is required. [Note: if a template is instantiated, errors will be diagnosed according to the other rules in this Standard. Exactly when these errors are diagnosed is a quality of implementation issue. ] [Example:

int j;
template<class T> class X {
    // ...
    void f(T t, int i, char* p)
    {
        t = i; // diagnosed if X::f is instantiated
               // and the assignment to t is an error
        p = i; // may be diagnosed even if X::f is
               // not instantiated
        p = j; // may be diagnosed even if X::f is
               // not instantiated
    }
    void g(T t) {
        +; //may be diagnosed even if X::g is
           // not instantiated
    }
};

end example]

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
0

The book you're looking at seems to reflect (mostly) that author's observations about how compilers really work, not the requirement(s) of the standard. The standard doesn't really say much to give extra leniency to a compiler about ill-formed code inside a template, just because it's not instantiated.

At the same time, the book is correct that there are some things a compiler really can't do much about checking until it's instantiated. For example, you might use a dependent name as the name of a function (or invoke it like a function, anyway -- if it's functor instead that would be fine too). If you instantiate that template over a class where it is a function, fine and well. If you instantiate it over a class where it's really an int, attempting to call it will undoubtedly fail. Until you've instantiated it, the compiler can't tell which is which though.

This is a large part of what concepts were really intended to add to C++. You could directly specify (for example) that template X will invoke T::y like a function. Then the compiler could compare the content of the template with the declarations in the concept, and determine whether the body of the template fit with the declaration in the concept or not. In the other direction, the compiler only needed to compare a class (or whatever) to the concept to determine whether instantiating that template would work. If it wasn't going to work, it could report the error directly as a violation of the relevant concept (as it is now, it tries to instantiate the template, and you frequently get some strange error message that indicates the real problem poorly, if at all).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111