user20562802
user20562802

Reputation:

consteval declaration mismatch works in MSVC but not in GCC and Clang

I've written the following program that compiles with msvc but not with gcc and clang. Demo

template<int x>
struct X {
consteval static int get();
int f() const;
};
//compiles with msvc but not with gcc and clang 
template<int x> int X<x>::get(){ return x; }  


int main() {
  constexpr int i = X<4>::get(); 
}

As we can see MSVC compiles the above demo while GCC and Clang reject it. GCC says:

error: redeclaration 'static int X<x>::get()' differs in 'consteval' from previous declaration
    8 | template<int x> int X<x>::get(){ return x; }
      |                     ^~~~
<source>:4:22: note: previous declaration 'static consteval int X<x>::get()'
    4 | consteval static int get();
      |                      ^~~
<source>: In function 'int main()':
<source>:12:30: error: 'static consteval int X<x>::get() [with int x = 4]' used before its definition
   12 |   constexpr int i = X<4>::get();
      |                     ~~~~~~~~~^~
<source>: At global scope:
<source>:4:22: warning: inline function 'static consteval int X<x>::get() [with int x = 4]' used but never defined
    4 | consteval static int get();
      |                      ^~~

I want to know which compiler is correct here according to the C++20 standard.

Upvotes: 5

Views: 167

Answers (1)

MSVC is wrong to accept this code silently. This is non-conforming, so it should at least print a diagnostic if it offers an extension (but I suspect it's accepted at all due to a bug).

[dcl.constexpr]

1 If any declaration of a function or function template has a constexpr or consteval specifier, then all its declarations shall contain the same specifier.

IIUC this rule exists due to some ODR-related implications. So GCC/Clang rejecting it outright is more sound.

Upvotes: 8

Related Questions