You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CWG3226 [temp.res.general] It seems wrong to restrict IFNDR when no valid specialization can be generated to when "the innermost enclosing template is not instantiated" #973
The program is ill-formed, no diagnostic required, if
(6.1) no valid specialization, ignoring static_assert-declarations that fail ([dcl.pre]), can be generated for a templated entity or a substatement of a constexpr if statement ([stmt.if]) within a templated entity and the innermost enclosing template is not instantiated, or
The intent of "and the innermost enclosing template is not instantiated" seems to be to remove the IFNDR status if an invalid specialization is actually produced, which in turn makes the program just IF. But the way it's currently worded is problematic.
Both GCC and Clang treat this->bar(); as IFNDR, which matches the intent. But since I have Foo<int> x;, which causes an instantiation of the innermost enclosing template (which is Foo), under the current wording the program turns from IFNDR to well-formed, which I guess isn't the intent.
I'm sure the intent is for this to be IFNDR, but since I have an instantiation of a<int>(), this is now well-formed.
Suggested resolution:
-and the innermost enclosing template is not instantiated+and that templated entity or substatement respectively is not instantiated
Or split the sentence to something like
+no valid specialization, ignoring static_assert-declarations that fail ([dcl.pre]), can be generated for a templated entity and that entity is not instantiated, or for a substatement of a constexpr if statement ([stmt.if]) within a templated entity and that substatement is not instantiated, or
I believe this isn't IFNDR, but rather a hard compiler error. Because this points to the class template Foo<T>, the expression this->bar() depends on the template parameter.
Under C++ template two-phase lookup rules, name lookup for a member of a dependent expression (this->bar()) is deferred until the template is instantiated (in this case it is Foo<int>).
When Foo<int> is instantiated, the compiler performs the lookup for bar inside Foo<int>. Since bar is never declared anywhere in Foo, the lookup fails, and the compiler must emit a diagnostic error message.
On x86-64 GCC 16.2:
<source>: In constructor 'Foo<T>::Foo(T)':
<source>:7:15: error: 'struct Foo<T>' has no member named 'bar' [-Wtemplate-body]
7 | this->bar();
| ^~~
@justs0coldFoo<int> f; doesn't instantiate the definition of the constructor Foo(T), only its declaration, so it can't cause this error. The error you're seeing is reported by GCC when first seeing the template, not when instantiating it (as you can see here by commenting out Foo<int> f;). GCC sees it as IFNDR under the "no valid specialization can be generated" rule.
My point is that the wording of "no valid specialization" rule is defective, because the wording says it becomes well-formed once I instantiate the enclosing class Foo<int>, even if I don't instantiate the offending constructor.
@HolyBlackCat Ah, you are completely correct. If I'm not wrong, GCC 15 and 16 introduced early diagnostic checks under the flag -Wtemplate-body, which analyzes the primary template definition, sees Foo<T> lacks a bar member for any generic type, and throws an error during phase 1.
changed the title [-][temp.res.general] It seems wrong to restrict IFNDR when no valid specialization can be generated to when "the innermost enclosing template is not instantiated"[/-][+]CWG3226 [temp.res.general] It seems wrong to restrict IFNDR when no valid specialization can be generated to when "the innermost enclosing template is not instantiated"[/+]on Aug 30, 2026
Activity
justs0cold commentedon Aug 29, 2026
I believe this isn't IFNDR, but rather a hard compiler error. Because
thispoints to the class templateFoo<T>, the expressionthis->bar()depends on the template parameter.Under C++ template two-phase lookup rules, name lookup for a member of a dependent expression (
this->bar()) is deferred until the template is instantiated (in this case it isFoo<int>).When
Foo<int>is instantiated, the compiler performs the lookup for bar insideFoo<int>. Sincebaris never declared anywhere inFoo, the lookup fails, and the compiler must emit a diagnostic error message.On x86-64 GCC 16.2:
HolyBlackCat commentedon Aug 29, 2026
@justs0cold
Foo<int> f;doesn't instantiate the definition of the constructorFoo(T), only its declaration, so it can't cause this error. The error you're seeing is reported by GCC when first seeing the template, not when instantiating it (as you can see here by commenting outFoo<int> f;). GCC sees it as IFNDR under the "no valid specialization can be generated" rule.My point is that the wording of "no valid specialization" rule is defective, because the wording says it becomes well-formed once I instantiate the enclosing class
Foo<int>, even if I don't instantiate the offending constructor.justs0cold commentedon Aug 29, 2026
@HolyBlackCat Ah, you are completely correct. If I'm not wrong, GCC 15 and 16 introduced early diagnostic checks under the flag
-Wtemplate-body, which analyzes the primary template definition, seesFoo<T>lacks abarmember for any generic type, and throws an error during phase 1.Apparently this:
can compile up to GCC 14.4.
jensmaurer commentedon Aug 30, 2026
CWG3226
[-][temp.res.general] It seems wrong to restrict IFNDR when no valid specialization can be generated to when "the innermost enclosing template is not instantiated"[/-][+]CWG3226 [temp.res.general] It seems wrong to restrict IFNDR when no valid specialization can be generated to when "the innermost enclosing template is not instantiated"[/+]