Bug 113110 - GCC rejects call to more specialized const char array version with string literal
Summary: GCC rejects call to more specialized const char array version with string lit...
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 13.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-12-22 04:18 UTC by Jason Liam
Modified: 2023-12-22 16:14 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jason Liam 2023-12-22 04:18:43 UTC
GCC seems to rejects valid code. The following code is rejected by gcc and clang while accepted by msvc. As the first version is more specialized for const char arrays, it seems the first version should be used. https://godbolt.org/z/anEnY44Te

```
#include <cstring>

using namespace std;

// fist version
template <size_t N, size_t M>
int compare(const char (&a)[N], const char (&b)[M]) {
    return strcmp(a, b);
}

// second version
template <typename T>
int compare(const T &a, const T &b) {
    if (a < b) return -1;
    if (b < a) return 1;
    return 0;
}

int main() {
    compare("dog", "cat"); //gcc and clang rejects while msvc accepts
}
```
Comment 1 Andrew Pinski 2023-12-22 05:07:09 UTC
EDG 6.5 also rejects the code:
```
<source>(21): error: more than one instance of overloaded function "compare" matches the argument list:
            function template "int compare(const char (&)[N], const char (&)[M])" (declared at line 8)
            function template "int compare(const T &, const T &)" (declared at line 14)
            argument types are: (const char [4], const char [4])
      compare("dog", "cat"); //gcc and clang rejects while msvc accepts
      ^

```

I suspect this is either a bug or an extension for MSVC.
Comment 2 Andrew Pinski 2023-12-22 05:17:12 UTC
I am almost want to say MSVC never implmented DR 214 which addresses this.


https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#214
Comment 3 Jason Liam 2023-12-22 05:18:24 UTC
(In reply to Andrew Pinski from comment #1)

> I suspect this is either a bug or an extension for MSVC.

Are you sure? I mean if you add another template parameter `U` to the second parameter and use it then gcc starts accepting the code and using the more specialized version. Demo:https://godbolt.org/z/W7Ma6c5Ts

This indicates that gcc was wrong in rejecting the original code. For reference here is the modified code which starts compiling with gcc: 

```
template <size_t N, size_t M>
int compare(const char (&a)[N], const char (&b)[M]) {
    return strcmp(a, b);
}
//--------------------vvvvvvvvvv-------->added this parameter
template <typename T, typename U>
//----------------------------v--------->changed this to U
int compare(const T &a, const U &b) {
    if (a < b) return -1;
    if (b < a) return 1;
    return 0;
}

int main() {
    compare("dog", "cat"); //now gcc also accepts it
}
```
Comment 4 Andrew Pinski 2023-12-22 05:21:38 UTC
(In reply to Jason Liam from comment #3)
> (In reply to Andrew Pinski from comment #1)
> 
> > I suspect this is either a bug or an extension for MSVC.
> 
> Are you sure? I mean if you add another template parameter `U` to the second
> parameter and use it then gcc starts accepting the code and using the more
> specialized version. Demo:https://godbolt.org/z/W7Ma6c5Ts


It is 3 compilers vs 1 here. Either there is some defect against the C++ standard or the odd one out has an issue ...
Comment 5 Andrew Pinski 2023-12-22 05:33:33 UTC
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=15674 also.

I am still suspecting MSVC of not implementing the C++ Defect report 214 .
Comment 6 Harald van Dijk 2023-12-22 10:19:15 UTC
(In reply to Jason Liam from comment #3)
> Are you sure? I mean if you add another template parameter `U` to the second
> parameter and use it then gcc starts accepting the code and using the more
> specialized version. Demo:https://godbolt.org/z/W7Ma6c5Ts

In order to determine whether int compare(const char (&)[N], const char (&)[M]) is more specialised than int compare(const T &, const T &), template argument deduction is attempted to solve one in terms of the other. Solving gives T = char[N] for the first parameter, but T = char[M] for the second parameter. This is a conflict that is ignored by MSVC.

When adding the second template parameter `U`, solving gives T = char[N], and U = char[M]. This is never a conflict, this unambiguously makes the array version more specialised.

(In reply to Andrew Pinski from comment #5)
> I am still suspecting MSVC of not implementing the C++ Defect report 214 .

At first glance, both GCC/clang and MSVC behaviour look like legitimate but different interpretations of DR 214. Whether MSVC is right to ignore that conflict is an open question covered by https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2160.