Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile error when using MSVC and template struct #108

Closed
AlexZhu2001 opened this issue May 31, 2024 · 5 comments
Closed

Compile error when using MSVC and template struct #108

AlexZhu2001 opened this issue May 31, 2024 · 5 comments

Comments

@AlexZhu2001
Copy link

Hi, I received some compilation errors when using MSVC with the following test code.

#include <string>
#include <rfl.hpp>
#include <rfl/json.hpp>

template <typename T>
struct A
{
    int code;
    std::string msg;
    T data;
};

struct B
{
    int some_val;
};

std::string test_case = R"(
{
    "code": 0,
    "msg": "hello",
    "data": {
        "some_val": 1
    }
}
)";

int main()
{
    auto resp = rfl::json::read<A<B>>(test_case).value();
    std::cout << "{" << std::endl
              << "  code: " << resp.code << std::endl
              << "  msg: " << resp.msg << std::endl
              << "  data: " << "{" << std::endl
              << "    some_val: " << resp.data.some_val << std::endl
              << "  }" << std::endl
              << "}" << std::endl;
}

This code works fine when using clang and mingw.
The msvc version is 19.29.30153 for x64
The compiled output is as follows

  reflectcpp.vcxproj -> E:\testproj\build-msvc\reflect-cpp\Debug\reflectcpp.lib
  main.cpp
E:\testproj\reflect-cpp\include\rfl\Literal.hpp(341,41): error C2338: Duplicate strings are not allowed in a Literal. [E:\testproj\build-msvc\main.vcxproj]
E:\testproj\reflect-cpp\include\rfl\internal/get_field_names.hpp(101): message : see reference to class template instantiation 'rfl::Literal<rfl::internal::StringLiteral<16>{std::array<char,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}},rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}>' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              _Ty=char
          ]
E:\testproj\reflect-cpp\include\rfl\internal/get_field_names.hpp(106): message : see reference to function template instantiation 'auto rfl::internal::concat_two_literals<rfl::internal::StringLiteral<16>{std::array<char,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}},rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}>(const rfl::Literal<rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}> &,const rfl::Literal<rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}> &)' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              _Ty=char
          ]
E:\testproj\reflect-cpp\include\rfl\internal/get_field_names.hpp(106): message : see reference to function template instantiation 'auto rfl::internal::concat_literals<rfl::Literal<rfl::internal::StringLiteral<16>{std::array<char,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}>,rfl::Literal<rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}>>(const Head &,const rfl::Literal<rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}> &)' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              _Ty=char,
              Head=rfl::Literal<rfl::internal::StringLiteral<16>{std::array<char,16>{char101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}>
          ]
E:\testproj\reflect-cpp\include\rfl\internal/get_field_names.hpp(144): message : see reference to function template instantiation 'auto rfl::internal::concat_literals<rfl::Literal<rfl::internal::StringLiteral<16>{std::array<char,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}>,rfl::Literal<rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}>,rfl::Literal<rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}>>(const Head &,const rfl::Literal<rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}> &,const rfl::Literal<rfl::internal::StringLiteral<16>{std::array<_Ty,16>{_Ty101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}> &)' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              _Ty=char,
              Head=rfl::Literal<rfl::internal::StringLiteral<16>{std::array<char,16>{char101,116,95,102,105,101,108,100,95,110,97,109,101,95,115,0}}>
          ]
E:\testproj\reflect-cpp\include\rfl\internal/get_field_names.hpp(146): message : see reference to function template instantiation 'auto rfl::internal::get_field_names::<lambda_1>::operator ()<0,1,2>(std::integer_sequence<size_t,0,1,2>) const' being compiled [E:\testproj\build-msvc\main.vcxproj]
E:\testproj\reflect-cpp\include\rfl\internal\to_ptr_named_tuple.hpp(70): message : see reference to function template instantiation 'auto rfl::internal::get_field_names<A<B>>(void)' being compiled [E:\testproj\build-msvc\main.vcxproj]
E:\testproj\reflect-cpp\include\rfl\internal\to_ptr_named_tuple.hpp(70): message : see reference to alias template instantiation 'rfl::field_names_t<A<B>&>' being compiled [E:\testproj\build-msvc\main.vcxproj]
E:\testproj\reflect-cpp\include\rfl\parsing\../to_view.hpp(14): message : see reference to function template instantiation 'auto rfl::internal::to_ptr_named_tuple<T&>(A<B>&)' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              T=A<B>
          ]
E:\testproj\reflect-cpp\include\rfl\parsing\StructReader.hpp(28): message : see reference to function template instantiation 'auto rfl::to_view<StructType>(T &)' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              StructType=A<B>,
              T=A<B>
          ]
E:\testproj\reflect-cpp\include\rfl\parsing\StructReader.hpp(25): message : while compiling class template member function 'rfl::Result<A<B>> rfl::parsing::StructReader<R,W,T,ProcessorsType>::read(const R &,const rfl::json::Reader::YYJSONInputVar &)' [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              R=rfl::json::Reader,
              W=rfl::json::Writer,
              T=A<B>,
              ProcessorsType=rfl::Processors<>
          ]
E:\testproj\reflect-cpp\include\rfl\parsing\Parser_default.hpp(58): message : see reference to function template instantiation 'rfl::Result<A<B>> rfl::parsing::StructReader<R,W,T,ProcessorsType>::read(const R &,const rfl::json::Reader::YYJSONInputVar &)' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              R=rfl::json::Reader,
              W=rfl::json::Writer,
              T=A<B>,
              ProcessorsType=rfl::Processors<>
          ]
E:\testproj\reflect-cpp\include\rfl\parsing\Parser_default.hpp(58): message : see reference to class template instantiation 'rfl::parsing::StructReader<R,W,T,ProcessorsType>' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              R=rfl::json::Reader,
              W=rfl::json::Writer,
              T=A<B>,
              ProcessorsType=rfl::Processors<>
          ]
E:\testproj\reflect-cpp\include\rfl\parsing\Parser_default.hpp(42): message : while compiling class template member function 'rfl::Result<A<B>> rfl::parsing::Parser<rfl::json::Reader,rfl::json::Writer,T,rfl::Processors<>>::read(const R &,const rfl::json::Reader::YYJSONInputVar &) noexcept' [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              T=A<B>,
              R=rfl::json::Reader
          ]
E:\testproj\reflect-cpp\include\rfl\json\read.hpp(24): message : see reference to function template instantiation 'rfl::Result<A<B>> rfl::parsing::Parser<rfl::json::Reader,rfl::json::Writer,T,rfl::Processors<>>::read(const R &,const rfl::json::Reader::YYJSONInputVar &) noexcept' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              T=A<B>,
              R=rfl::json::Reader
          ]
E:\testproj\reflect-cpp\include\rfl\json\read.hpp(22): message : see reference to class template instantiation 'rfl::parsing::Parser<rfl::json::Reader,rfl::json::Writer,T,rfl::Processors<>>' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              T=A<B>
          ]
E:\testproj\reflect-cpp\include\rfl\json\read.hpp(29): message : see reference to function template instantiation 'rfl::Result<A<B>> rfl::json::read<T,>(const rfl::json::InputVarType &)' being compiled [E:\testproj\build-msvc\main.vcxproj]
          with
          [
              T=A<B>
          ]
E:\testproj\main.cpp(30): message : see reference to function template instantiation 'rfl::Result<A<B>> rfl::json::read<A<B>,>(const std::string &)' being compiled [E:\testproj\build-msvc\main.vcxproj]
@AlexZhu2001
Copy link
Author

By the way, it seems that only this version of MSVC will have this error, while version 19.38.33133 of MSVC does not seem to have any errors.

@liuzicheng1987
Copy link
Contributor

This is very interesting, thanks for the issue. What is clearly happening is that get_field_name_str_view is not doing what it is supposed to be doing:

https://github.com/getml/reflect-cpp/blob/main/include/rfl/internal/get_field_names.hpp

I will try to reproduce the problem.

liuzicheng1987 added a commit that referenced this issue May 31, 2024
@liuzicheng1987
Copy link
Contributor

Hi @AlexZhu2001 , so the reason it doesn't compile with 19.29.30153 is that the version for the compiler is simply too old. It doesn't have anything to do with the templating.

As we clearly state in our README, reflect-cpp requires at least MSVC 17.8, which corresponds to version 19.38. (MSVC versioning numbering is very confusing...) As you have correctly observed, it works for 19.38.

Take this simple example program:

#include <source_location>
#include <string_view>
#include <iostream>
#include <string>

template <class T, auto ptr>
consteval auto get_field_name_str_view() {
  const auto func_name = std::string_view{std::source_location::current().function_name()};
  const auto split = func_name.substr(0, func_name.size() - 7);
  return split.substr(split.rfind("->") + 2);
}

struct Test{int a;};

static constexpr auto test = Test{};

consteval auto get_f1() {
  auto& [f1] = test;
  return &f1;
}


int main(int argc, const char** argv) {  
  constexpr auto ptr = get_f1();
  constexpr auto str = get_field_name_str_view<Test, ptr>();
  static_assert(get_field_name_str_view<Test, &test.a>() == "a", "Failed");
  std::cout << str << std::endl;
  return 0;
}

You can insert it in godbolt.org...it compiles with 19.38, no problem. But it will fail with 19.29.

@liuzicheng1987
Copy link
Contributor

@AlexZhu2001, I have added your example as a test:

https://github.com/getml/reflect-cpp/blob/f/templates/tests/json/test_template.cpp

As you can see, the Github Action pipelines run through for all compilers, including MSVC:

https://github.com/getml/reflect-cpp/commits/f/templates/

So I would argue that this is simply an issue with an unsupported compiler.

But thank you for opening this issue. At the very least, we got another test out of it.

@AlexZhu2001
Copy link
Author

Okay, the version number of MSVC is really confusing. I will upgrade to the corresponding supported version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants