veselink1 / refl-cpp

Static reflection for C++17 (compile-time enumeration, attributes, proxies, overloads, template functions, metaprogramming).
https://veselink1.github.io/refl-cpp/md__introduction.html
MIT License
1.05k stars 76 forks source link

Compiler error on Visual Studio 2019 but not on XCode (GCC) #52

Closed rpatters1 closed 2 years ago

rpatters1 commented 2 years ago

I am trying to get some code working that processes properties. Part of what I need to do is, given a getter, to find the corresponding setter. My plan is to look for a writable property with the same friendly_name. If there is a more direct way to find the setter that matches a getter, I would not need to do this.

This code compiles and works on XCode/GCC. It produces a lot of errors (and eventually crashes) Visual Studio 2019. If it's a compiler bug, any suggestions for a workaround would be appreciated. If it's a bug in my code, I'd be very grateful to know how to fix it. The problem appears to be the call to get_display_name_const.

struct foo {
   int _bar;
   int get_bar() const {return _bar;}
   void set_bar(int val) {_bar = val;}
};
REFL_AUTO
(
   type(foo),
   func(get_bar, property()),
   func(set_bar, property())
)
template<class T>
static void ProcessClass()
{
   constexpr auto type = refl::reflect<T>();
   constexpr auto members = get_members(type);

   for_each(members, [&](auto member)
   {
      if constexpr (refl::descriptor::is_property(member) && ! refl::descriptor::is_writable(member))
      {
         // this line causes compile errors on Visual Studio 2019
         // comment it out and the program compiles without error   
         constexpr auto prop_name = refl::descriptor::get_display_name_const(member);
      }
   });
}
static void my_runtime_func()
{
   ProcessClass<foo>();
}

The errors look something like this:

1>C:\myprogram\refl-cpp\include\refl.hpp(207,49): error C2589: '(': illegal token on right side of '::'
1>C:\myprogram\refl-cpp\include\refl.hpp(3258): message : see reference to function template instantiation 'auto refl::util::const_string<7>::substr<0,3>(void) noexcept const' being compiled
1>C:\myprogram\refl-cpp\include\refl.hpp(3284): message : see reference to function template instantiation 'auto refl::descriptor::detail::normalize_accessor_name<T>(const T)' being compiled
1>        with
1>        [
1>            T=refl::descriptor::function_descriptor<foo,0>
1>        ]
1>C:\myprogram\refl-cpp\include\refl.hpp(3335): message : see reference to function template instantiation 'auto refl::descriptor::detail::get_display_name<Descriptor>(const T) noexcept' being compiled
1>        with
1>        [
1>            Descriptor=refl::descriptor::function_descriptor<foo,0>,
1>            T=refl::descriptor::function_descriptor<foo,0>
1>        ]
1>C:\myprogram\-Source\myprogram.cpp(165): message : see reference to function template instantiation 'auto refl::descriptor::get_display_name_const<_Ty>(Descriptor) noexcept' being compiled
1>        with
1>        [
1>            _Ty=refl::descriptor::function_descriptor<foo,0>,
1>            Descriptor=refl::descriptor::function_descriptor<foo,0>
1>        ]
1>C:\myprogram\refl-cpp\include\refl.hpp(1557): message : see reference to function template instantiation 'auto ProcessClass::<lambda_b6ce6e654e3e0c33c3e1dc4678e74867>::operator ()<_Ty>(_Ty) const' being compiled
1>        with
1>        [
1>            _Ty=refl::descriptor::function_descriptor<foo,0>
1>        ]
1>C:\myprogram\refl-cpp\include\refl.hpp(1551): message : see reference to function template instantiation 'auto refl::util::for_each::<lambda_75c4d1b1bd375369e623ef71284a8c59>::operator ()<_Ty>(_Ty &&,size_t) const' being compiled
1>        with
1>        [
1>            _Ty=refl::descriptor::function_descriptor<foo,0>
1>        ]
1>C:\myprogram\refl-cpp\include\refl.hpp(1601): message : see reference to function template instantiation 'auto refl::util::detail::eval_in_order_to_tuple<_Ty,refl::descriptor::function_descriptor<T,0>,refl::descriptor::function_descriptor<T,1>,0,1,>(refl::util::type_list<refl::descriptor::function_descriptor<T,0>,refl::descriptor::function_descriptor<T,1>>,std::integer_sequence<size_t,0,1>,F &&)' being compiled
1>        with
1>        [
1>            _Ty=refl::util::for_each::<lambda_75c4d1b1bd375369e623ef71284a8c59>,
1>            T=foo,
1>            F=refl::util::for_each::<lambda_75c4d1b1bd375369e623ef71284a8c59>
1>        ]
1>C:\myprogram\refl-cpp\include\refl.hpp(1634): message : see reference to function template instantiation 'auto refl::util::map_to_tuple<refl::util::for_each::<lambda_75c4d1b1bd375369e623ef71284a8c59>,refl::descriptor::function_descriptor<T,0>,refl::descriptor::function_descriptor<T,1>>(refl::util::type_list<refl::descriptor::function_descriptor<T,0>,refl::descriptor::function_descriptor<T,1>>,F &&)' being compiled
1>        with
1>        [
1>            T=foo,
1>            F=refl::util::for_each::<lambda_75c4d1b1bd375369e623ef71284a8c59>
1>        ]
1>C:\myprogram\-Source\myprogram.cpp(167): message : see reference to function template instantiation 'void refl::util::for_each<ProcessClass::<lambda_b6ce6e654e3e0c33c3e1dc4678e74867>,refl::descriptor::function_descriptor<T,0>,refl::descriptor::function_descriptor<T,1>>(refl::util::type_list<refl::descriptor::function_descriptor<T,0>,refl::descriptor::function_descriptor<T,1>>,F &&)' being compiled
1>        with
1>        [
1>            T=foo,
1>            F=ProcessClass::<lambda_b6ce6e654e3e0c33c3e1dc4678e74867>
1>        ]
1>C:\myprogram\-Source\myprogram.cpp(171): message : see reference to function template instantiation 'void ProcessClass<foo>(void)' being compiled
1>C:\myprogram\refl-cpp\include\refl.hpp(207): error C2062: type 'unknown-type' unexpected
1>C:\myprogram\refl-cpp\include\refl.hpp(207,1): error C2059: syntax error: ')'
1>C:\myprogram\refl-cpp\include\refl.hpp(209,34): error C2131: expression did not evaluate to a constant
1>C:\myprogram\refl-cpp\include\refl.hpp(209,26): message : failure was caused by a read of an uninitialized symbol
1>C:\myprogram\refl-cpp\include\refl.hpp(209,26): message : see usage of 'NewSize'
1>C:\myprogram\refl-cpp\include\refl.hpp(211,28): error C3863: array type 'char [NewSize+1]' is not assignable
1>C:\myprogram\refl-cpp\include\refl.hpp(214,1): error C2971: 'refl::util::const_string': template parameter 'N': 'NewSize': a variable with non-static storage duration cannot be used as a non-type argument
1>C:\myprogram\refl-cpp\include\refl.hpp(127): message : see declaration of 'refl::util::const_string'
1>C:\myprogram\refl-cpp\include\refl.hpp(207): message : see declaration of 'NewSize'
1>C:\myprogram\refl-cpp\include\refl.hpp(214,1): fatal error C1903: unable to recover from previous error(s); stopping compilation
1>INTERNAL COMPILER ERROR in 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\HostX86\x64\CL.exe'
1>    Please choose the Technical Support command on the Visual C++
1>    Help menu, or open the Technical Support help file for more information
rpatters1 commented 2 years ago

This error was caused by too many REFL_AUTO macros in one .cpp file. The Visual Studio compiler can only process these in small-to-moderate sized gulps.