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

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

Problem Description:

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.

Solution – 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.

Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept
Reject