5

Consider the following example

template <typename A> struct S 
{
  A a;
  void foo() {}
};  

template <typename T> void bar()
{
  S<void> *p = 0;
}

template <typename T> void baz()
{
  S<void>{}.foo();
}

template <typename T> void qux()
{
  S<void> s{};
}

int main()
{
}

Function templates bar, baz and qux are deliberately left non-instantiated.

The definition of baz fails to compile in GCC and Clang for "obvious" reason - S<void> is an invalid specialization of S. However, which language rule is working in this case?

  1. On the one hand, S<void> does not depend on template parameters of baz, member access requires it to be complete, which triggers instantiation of S<void>, which fails. Diagnostic is required.

  2. On the other hand we have the blanket rule of "if no valid specialization can be generated for a non-instantiated template, the code is ill-formed". This makes the definition of baz ill-formed. However, no diagnostic is required.

More specifically, am I correct in my assumption (as expressed in #1) that the above reference to S<void> from non-instantiated baz requires instantiation of S<void>? The assumption is supported by the fact that both compilers happily accept the definition of bar, which does not instantiate S<void>.

However, the aforementioned compilers differ in their treatment of qux - Clang complains, while GCC accepts it without any complaints. Is this a bug in one of the compilers? Is diagnostic required in this case? Or am I wrong in my assumption that #1 is at work here? If #2 is the basis for the diagnostic, then the difference between the compilers is acceptable.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765

2 Answers2

1

For both baz and qux, the validity of the expression including S<void> can only be done through instantiation of S. Nevertheless, compilers are not mandated to perform this validation before any instantiation [temp.res]/8

The validity of a template may be checked prior to any instantiation. [...  ] The program is ill-formed, no diagnostic required, if:

  • 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,
Oliv
  • 17,610
  • 1
  • 29
  • 72
1

Both S<void>{} and S<void> s{} are used in a context that requires the instantiation of S<void>, such an instantiation is ill-formed due to the member having incomplete type void.

The relevant quotes are [temp.inst]/1:

Unless a class template specialization has been explicitly instantiated or explicitly specialized, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. [...]

and [temp.arg]/6:

If the use of a template-argument gives rise to an ill-formed construct in the instantiation of a template specialization, the program is ill-formed.

On the other hand both baz and quz are ill-formed NDR [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:

(8.1) no valid specialization can be generated for a template, [...]

Community
  • 1
  • 1
Jans
  • 11,064
  • 3
  • 37
  • 45