2

I am learning C++ templates using the resource listed here. In particular, read about template argument deduction. Now, after reading, to further clear up my concept of the topic I tried the following example that compiles in gcc but not in clang and msvc. Demo

template<typename T = int> void f()
{

}
template<typename T> void func(T)
{

}
int main()
{
    func(f); //works in gcc but not in clang and msvc 
    func(f<>); //works in all
}

As we can see, the above example compiles fine in gcc but not in clang and msvc. My question is which compiler is right here according to the latest standard?

Jason
  • 36,170
  • 5
  • 26
  • 60
Kal
  • 475
  • 1
  • 16
  • I think that gcc is right. – Jason Aug 19 '22 at 10:42
  • I think GNU C++ is using an extension to the Standard. – Adrian Mole Aug 19 '22 at 10:45
  • My legalese is not so hot when it comes to templates but the C++17 Draft Standard has this in 17.9.2.1 paragraph 5: *Note:* If a *template-parameter* is not used in any of the function parameters of a function template, or is used only in a non-deduced context, its corresponding *template-argument* cannot be deduced from a function call and the *template-argument* must be explicitly specified. — *end note* In the second case, the empty `<>` explicitly specifies the default argument. – Adrian Mole Aug 19 '22 at 10:50

1 Answers1

2

This is CWG 2608 and the program is well-formed so that gcc is correct in accepting the program.


From temp.arg.explicit#4 which was added due to cwg 2608, the default template argument can be used and the empty template argument list <> can be omitted.

If all of the template arguments can be deduced or obtained from default template-arguments, they may all be omitted; in this case, the empty template argument list <> itself may also be omitted.

(emphasis mine)

Note the bold highlighted part in the above quoted statement, which means that the empty template argument list <> can be omitted in your example because all of the template arguments can be obtained from default template-arguments.

Further, over.over#3 can also be used here to see that the specialization generated from temp.arg.explicit is added to the overloaded set:

The specialization, if any, generated by template argument deduction ([temp.over], [temp.deduct.funcaddr], [temp.arg.explicit]) for each function template named is added to the set of selected functions considered.

(emphasis mine)

This means that at the end, the call func(f); is well-formed and uses the generated specialization f<int>.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • So, is this something that changed between C++17 and C++20? Unfortunately, OP has not specified a version of the Standard - but uses both C++17 and C++20 in the linked Compiler Explorer example. – Adrian Mole Aug 19 '22 at 10:52
  • @AdrianMole Yes it was changed in the latest standard. Like some notes were removed etc. Also, note that OP has written in their question that they're looking for the **latest standard** compatible answer so i've answered accordingly. – Jason Aug 19 '22 at 10:54
  • OK - I must have skipped the "latest standard" part. :( – Adrian Mole Aug 19 '22 at 10:55
  • 1
    I don't get. How the addition of «or obtained from default template-arguments» will cancel «If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails»? Obtaining from default template-argument ≠ explicitly specified. – Language Lawyer Aug 19 '22 at 11:12
  • Hm. Wait. Which `T` you say is in non-deduced context? `f`'s or `func`'s? – Language Lawyer Aug 19 '22 at 11:44
  • Ok, after re-reading the answer, could you clarify on the transition from Step 1 to Step 2? Deduction for `func`'s `T` fails and then we generate a specialization from `f` using default argument, throw away the template from the overloaded set so that there is no non-deduced context anymore, and retry deduction of `func`'s `T` again? – Language Lawyer Aug 19 '22 at 13:37
  • _`func(f)` behaves the same as `func(f<>)`_ So, with 2608, the overload set for `f` no longer contains template, but consists only of the specialization `f`? – Language Lawyer Aug 19 '22 at 14:06
  • Why the deduction fails then, if there are no templates in the overload set? – Language Lawyer Aug 19 '22 at 14:27
  • 1
    5.5.1 applies, but somehow deduction is still succeeds for non-deduced `func`'s `T`? Funny… – Language Lawyer Aug 19 '22 at 14:35
  • 1
    _deduction does not succeed_ Why _the program is well-formed so that gcc is correct in accepting the program_ then? – Language Lawyer Aug 19 '22 at 14:41
  • But `func` does not have default template args – Language Lawyer Aug 19 '22 at 14:42
  • @LanguageLawyer Continued... I think what you're saying is that since the deduction has already failed we should get a hard error? – Jason Aug 19 '22 at 14:55
  • 1
    You either: 1. Fail deduction because overload set contains a function template 2. Do not fail deduction because there is no function template in overload set (then the reference to 5.1.1 is not relevant) 3. First fail the deduction but then somehow get rid of the function template in the overload set and perform deduction again. For this case, your answer is missing the relevant wording – Language Lawyer Aug 19 '22 at 15:00
  • _And the final and third way is that T gets obtained from default argument_ And where is `func`'s default argument? – Language Lawyer Aug 19 '22 at 15:22