Weird template specialization errors

Anonymous
2022-08-13T11:56:18.76+00:00

EDIT

I managed to create a minimal example showing the problem :

template <typename T> struct SizeT { T x; T y; };  
struct TwoFloats { float x; float y; };  
  
namespace helper  
{  
    template <typename T> bool Peek( T * value );  
    template <typename T , typename ...ARGS> bool Peek( T * value , ARGS ...args );  
  
    template <> bool Peek( TwoFloats * value );  
  
    template <typename T> inline bool Peek( SizeT<T> * value )  
    {  
        TwoFloats tf;  
        if ( !Peek( &tf ) )  
            return false;  
        value->x = static_cast<T>( tf.x );  
        value->y = static_cast<T>( tf.y );  
        return true;  
    }  
}  
  
template <> bool helper::Peek( TwoFloats * value )  
{  
    return false;  
}  
  
int main( )  
{  
    return 0;  
}  

This file doesn't compile using visual studio 2019,2022. gcc and clang compile it without issues. If I comment out the declaration of Peek<T,...ARGS> or do not use Peek<TwoFloats>( ) call in Peek<Size>( ) the error goes away. The error also goes away if I move the Peek<TwoFloats>( ) specialization inside the namespace braces.

Is there anything wrong with the code above , or is it a compiler bug ?

Original question

I have a somewhat large c++ project which uses visual studio 2017, which I am trying to migrate to visual studio 2022. The only weird issue I am facing is with two instances (among many) of weird errors concerning template specializations.

In the code there is a namespace LuaHelper, with two template functions in it:

namespace LuaHelper  
{  
    template <typename T> void Push( lua_State * lua_state , const T & value );  
    template <typename T> bool Peek( lua_State * lua_state , int offset , T * value );  
}  

And there are a lot of classes which specialize their own push and peek methods. Currently the code looks something like this (wrapped in macros):

// forward declaration in common header  
namespace LuaHelper  
{  
    template <> void Push( lua_State * lua_state , const Vector2D & value );  
    template <> bool Peek( lua_State * lua_state , int offset , Vector2D * value );  
}  

// actual code in vector2d wrapper cpp file  
template <> void LuaHelper::Push( lua_State * lua_state , const Vector2D & value ) { /* actual code */ }  
template <> bool LuaHelper::Peek( lua_State * lua_state , int offset , Vector2D * value ) { /* actual code */ }  

There are 30+ classes being specialized the same way and visual studio 2017 and gcc are compiling those fine. The weird thing is that trying to compile the same code with vs2022 or vs2019 there are exactly 2 errors:

  1. error C2244: 'Peek': unable to match function definition to an existing declaration -- for one of the classes
    and
  2. error C2244: 'Push': unable to match function definition to an existing declaration -- for another one

It is really baffling, why would the Push() specialization be accepted for 30 classes, but fail for just one. Same goes for peek. It doesn't help that for the Vector2D class, where Peek specialization complains, the Push( ) specialization compiles fine. There doesn't seem to be any difference in declarations for any of those classes.

The only workaround I managed to find is to wrap the specialization code in namespace braces, something like:

// actual code in vector2d wrapper cpp file  
namespace LuaHelper  
{  
  template <> void Push( lua_State * lua_state , const Vector2D & value ) { /* actual code */ }  
  template <> bool Peek( lua_State * lua_state , int offset , Vector2D * value ) { /* actual code */ }  
}  

this makes compiler happy, and stops the C2244 errors.

It's somewhat funny that I had to wrap in namespace just the code in two of the cpp files, all other classes are still outside of the namespace and the compiler doesn't mind it at all.

Am I doing something wrong here? Any hints of what might be causing this? This really feels like a compiler bug, but unfortunately it's pretty hard to create an empty project reproducing the issue, it seems to compile fine when the same code is isolated.

Thank you!

Developer technologies | C++
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.