1

If a C++ template contains a blatant type error, such as a reference to a class member that does not exist, does the language standard guarantee to detect the error at the time the template is defined?

Or is the error guaranteed to be detected only when the template is instantiated?

  1. Suppose the error does not involve any of the template parameters?

  2. Suppose it does involve one of the template parameters?

user7610
  • 25,267
  • 15
  • 124
  • 150
Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • 2
    How would you check the parameter types without specifying them (i.e. instantiating the template)? Maybe I didn't understand your question, but there are of course possibilities to check the template parameters for constraints, but you need to have concrete types to do so. So your 3rd point describes the behavior at best IMO. – πάντα ῥεῖ Jun 09 '16 at 16:24
  • 1
    Unclear what you are asking. What do you mean by *typechecking templates*? Template parameter substitution? – Ivan Aksamentov - Drop Jun 09 '16 at 16:34
  • @Drop OP obviously means constraint checks (aka. concepts). – πάντα ῥεῖ Jun 09 '16 at 16:39
  • 1
    There is a Two-Phase for template, one for non template dependent stuff, and an other for template dependent stuff. (visual doesn't respect that btw). – Jarod42 Jun 09 '16 at 16:44
  • @Drop OK, I'm at least not that sure that this is obvious. The question is unclear. It would be at least good style to give a little code sample with a template, and asking which parts would be checked would be checked by the compiler without instantiation. – πάντα ῥεῖ Jun 09 '16 at 16:57
  • @πάνταῥεῖ you would check parameter types against some form of constraint like a CLU where clause, and ML signature, or a C++ concept---if such things are real. The CLU and ML examples are emphatically real. – Norman Ramsey Jun 09 '16 at 16:58
  • @πάνταῥεῖ If I knew enough C++ to write an example template, I probably would not have to ask the question. – Norman Ramsey Jun 09 '16 at 16:58
  • @NormanRamsey Well, I tried to explain at my best in my answer how that works. But my premise was mostly about constraint checks upon the parameters. – πάντα ῥεῖ Jun 09 '16 at 17:03
  • @NormanRamsey Well, now you have drastically changed your question (not nice). You may have provided the summary you have now as an addendum, instead of completely delete the original content. Good that I cited your original question in my answer. – πάντα ῥεῖ Jun 09 '16 at 17:16
  • @NormanRamsey _"If I knew enough C++ to write an example template ..."_ Didn't you have something (concrete) in mind when asking? E.g. to solve a particular problem, or are you just asking for curiosity (may be based and triggered by your compiler construction backgrounds)? Finally you may add the [tag:language-lawyer] tag, to get any answers grounded on the official c++ standard specifications. – πάντα ῥεῖ Jun 09 '16 at 18:04
  • @NormanRamsey Do you want to [join this discussion](https://chat.stackoverflow.com/transcript/message/31065422#31065422)? – πάντα ῥεῖ Jun 09 '16 at 19:17

2 Answers2

1

Checking is allowed, but not required. [temp.res]/8:

Knowing which names are type names allows the syntax of every template to be checked. The program is ill-formed, no diagnostic required, if:

  • no valid specialization can be generated for a template and that template is not instantiated, or

  • every valid specialization of a variadic template requires an empty template parameter pack, or

  • a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or

  • the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the template.

Note that two-phase lookup doesn't actually require early checking: various name lookups are required to be done in the template definition context, but they are not actually required to be done at the time of definition.

T.C.
  • 133,968
  • 17
  • 288
  • 421
0

As for your (original) title

Can a C++ template be typechecked without instantiating it?

Depends on what exactly is meant with typecheck.


does the language standard guarantee to detect the error at the time the template is defined?

Regarding the template declaration (!) and definition itself, it will be checked for syntactical correctness before instantiation, as you mentioned in your question.

There is some type checking done ...

template<typename T>
class Foo {
     Foo() : x(y) {}
private:
     int &x;
     T z;
};

int main() {
} 

clang =============
main.cpp:4:20: error: use of undeclared identifier 'y'
         Foo() : x(y) {}
                   ^
1 error generated.
gcc =============
main.cpp: In constructor 'Foo<T>::Foo()':
main.cpp:4:20: error: 'y' was not declared in this scope
          Foo() : x(y) {}
                    ^

See the Demo


... but not consistently with

template<typename T>
class Foo {
     Foo() : x(Foo::y) {}
private:
     int &x;
     T z;
};

int main() {
}

clang =============
main.cpp:4:25: error: no member named 'y' in 'Foo<T>'
         Foo() : x(Foo::y) {}
                   ~~~~~^
1 error generated.
gcc =============

Demo


Where GCC also throws an error, when Foo is actually instantiated:

template<typename T>
class Foo {
public:
     Foo() : x(Foo::y) {}
private:
     int &x;
     T z;
};

int main() {
    Foo<int> foo; // <<<<<<<<<<<<<<<<<<<<<
}

clang =============
main.cpp:5:25: error: no member named 'y' in 'Foo<T>'
         Foo() : x(Foo::y) {}
                   ~~~~~^
1 error generated.
gcc =============
main.cpp: In instantiation of 'Foo<T>::Foo() [with T = int]':
main.cpp:12:18:   required from here
main.cpp:5:26: error: 'y' is not a member of 'Foo<int>'
          Foo() : x(Foo::y) {}
                          ^

Demo

Or is the error guaranteed to be detected only when the template is instantiated?

So this seems to be true.


How far that goes seems to be a compiler implementation specific detail.
So no, obviously there are no standard guarantees regarding that.

Also as @Jarod42 has shown in their Clang/GCC sample

template <typename T>
void foo()
{
    int a = "hello world";
    const char* hello = 42;
}

int main()
{
}

clang =============
main.cpp:6:9: error: cannot initialize a variable of type 'int' with an lvalue of type 'const char [12]'
    int a = "hello world";
        ^   ~~~~~~~~~~~~~
main.cpp:7:17: error: cannot initialize a variable of type 'const char *' with an rvalue of type 'int'
    const char* hello = 42;
                ^       ~~
2 errors generated.
gcc =============

So I'm afraid there's nothing more available than can be found in section §14.5 of the c++ standard specification what is considered valid template declaration/definition syntax.



Regarding former versions of your question:

I'd like to know how much type checking can be done with a template definition, before the template is instantiated.

The compiler needs to see the concrete parameter types (and non type parameter values) to apply (and in turn instantiate) the constraint checking templates for these types.

So the template must be instatiated to do this.


  • Perhaps a template is a lot like a macro in Lisp: the compiler checks the syntax, but no typechecking is done until the template is instantiated. And each time the template is instantiated, the compiler runs the typechecker again.

That seems to come closest, though there's nothing like a typechecker that runs during compilation, but mostly instantiating other template classes and let a std::static_assert decide in the end, if the constraints for the type (or non type) parameter are met or not.


To see how the c++ standard library deals with that, see Library Concepts please.


Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Clang does some typechecking without instantiation (for non template dependent types): [Demo](http://coliru.stacked-crooked.com/a/f0fa7b04afeddf2b). – Jarod42 Jun 09 '16 at 16:49
  • @Jarod42 I just updated my answer while wrote this comment. Of course the template declaration and definition is checked (not only with clang IIRC). The question is really unclear indeed. – πάντα ῥεῖ Jun 09 '16 at 16:52
  • 1
    I was under the impression that 'concepts' were still an experimental feature and not yet really part of the standard. Has that changed? – Norman Ramsey Jun 09 '16 at 16:54
  • I'm surprised that gcc doesn't emit errors for the given code :-/ – Jarod42 Jun 09 '16 at 16:54
  • BTW, I have written C compilers. There is definitely a typechecker that runs during compilation. See for example, Fraser and Hanson, *A Retargetable C Compiler*, basics starting in Chapter 4. – Norman Ramsey Jun 09 '16 at 16:56
  • @NormanRamsey I probably misunderstood that term for _constraint checker_. I didn't wan't to belittle you in any way though, I'm sorry if I got you some feeling in that direction. – πάντα ῥεῖ Jun 09 '16 at 17:13
  • @NormanRamsey _"I was under the impression that 'concepts' were still an experimental feature"_ _Concepts_ are live up to some degree, see my link. – πάντα ῥεῖ Jun 09 '16 at 19:31