5

The following C++ code does not compile e.g. with g++-4.7 or clang++-3.2:

struct Bar {};

template<typename T>
void foo(T t, Bar bar) {
    t.compiler_does_not_care();
    bar.nonexistent_method();
}

int main() {}

Why do compilers check the code of the template function foo for semantic correctness (where they can) even though it is never instantiated? Is this standard compliant?

user1225999
  • 912
  • 8
  • 14
  • 2
    Why should it _not_ check for semantic correctness? What's the point of a template that you can't instantiate? – davmac Aug 20 '14 at 13:27
  • Read about [*two-phase lookup*](http://stackoverflow.com/questions/7767626/two-phase-lookup-explanation-needed). And [use MS Visual C++ if you don't like such behavior](http://rextester.com/NBQGR37653). – Constructor Aug 20 '14 at 13:32
  • I would expect the compiler to do the minimum work required to compile the code, which would only require syntactic correctness of foo in order to skip the code of foo if it does not get instantiated. This code is somewhat oversimplified. Say the code can be configured in various ways: In some configurations Bar contains the method and foo gets instantiated and in some other configurations Bar does not contain the method and foo does not get instantiated. The software package I have at hand heavily makes use of such constructs. Often it is not a problem since Bar depends on a template. – user1225999 Aug 20 '14 at 13:41

1 Answers1

7

Bar is a non dependent name (i.e. its type does not depend on T), so the compiler is required to verify the correctness of the code during the first phase of name-lookup (see the note below).

Since Bar has no nonexistent_method() method, the compiler is required to issue a diagnosis.

If you change your template to:

template<typename T>
void foo(T t, T bar) {
    t.compiler_does_not_care();
    bar.nonexistent_method();
}

No non-dependent names are involved, so no error is emitted since the template is never instantiated (phase 2 of the lookup)


Notes:

  • Comprehensible description of two-phase name lookup from LLVM :

1) Template definition time: when the template is initially parsed, long before it is instantiated, the compiler parses the template and looks up any "non-dependent" names. A name is "non-dependent" if the results of name lookup do not depend on any template parameters, and therefore will be the same from one template instantiation to another.

2) Template instantiation time: when the template is instantiated, the compiler looks up any "dependent" names, now that it has the full set of template arguments to perform lookup. The results of this lookup can (and often do!) vary from one template instantiation to another.

  • As for the why non-dependent name lookup can't be deferred to the second stage, see this other SO post; it seems that it is mostly for historical reasons.
Community
  • 1
  • 1
quantdev
  • 23,517
  • 5
  • 55
  • 88