The following code compiled well in trunk gcc and clang, but failed in msvc for c++20 mode:
template <typename T = int>
void f(void* ptr, T&& t = {}) {
if (ptr) {
f(nullptr);
}
}
with the messages:
error C2672: 'f': no matching overloaded function found note: could be 'void f(void *,T &&)' note: 'void f(void *,T &&)': could not deduce template argument for 'T' note: 'f': function declaration must be available as none of the arguments depend on a template parameter
Works well for msvc for c++17 mode, since /permissive- is only available by default since c++20.
Can be easily fixed for msvc c++20 by specifying template type explicitly, i.e. f<T>(nullptr); in the function body.
Who is right according to the standard? I’m interested for both c++17 and c++20 modes. Is there any changes will come with upcoming c++23?
>Solution :
This is CWG 2608 and the program is well-formed and gcc and msvc are standard conformant.
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)
This means that f(nullptr); is well-formed as the template argument for T can be obtained from the default template argument and hence it may be omitted which implies that the empty template argument list <> itself may also be omitted. Thus, gcc and clang are standard conformant. Note also that msvc compiles this with /permissive so there is no reason to submit a bug report since they usually advise to use /permissive flag before submitting bugs.
You can also confirm this by adding empty <> and you will notice that msvc then compiles the program. Demo
template <typename T = int>
void f(void* ptr, T&& t = {}) {
if (ptr) {
//-------vv-------------->msvc compiles this with empty <> - See CWG 2608
f<>(nullptr);
}
}