cereal icon indicating copy to clipboard operation
cereal copied to clipboard

Multiple defined symbols for CEREAL_CLASS_VERSION after update to VS 15.8

Open cstamatopoulos opened this issue 7 years ago • 4 comments

After upgrading to VS v15.8 I am getting a linker error for 2 out of many classes that are serialized using cereal. Anyone has similar issues ? Commenting out the CEREAL_CLASS_VERSION(MyClass, 1); from the 2 header files solves the issue but that is not helpful of course.

The error is something like this.

error LNK2005: "public: static unsigned int const cereal::detail::Version<class MyClass,struct cereal::detail::`anonymous namespace'::version_binding_tag>::version" (?version@?$Version@MyClass@@Uversion_binding_tag@?A0x58adc01e@detail@cereal@@@detail@cereal@@2IB) already defined in same_file.obj

cstamatopoulos avatar Aug 14 '18 19:08 cstamatopoulos

I have a similar issue on release build with VS 15.8. It looks like the CEREAL_CLASS_VERSION should be in cpp file and that it is used is header file is the problem here.

runarundheim avatar Aug 16 '18 05:08 runarundheim

When I moved the version registration into the cpp files I solved my problems.

runarundheim avatar Aug 16 '18 08:08 runarundheim

That would make sense if it was a full specialization. I remember seeing this in the past but there is a tag added for that reason, and here is the explanation from cereal's source.

//! Tag for Version, which due to its anonymous namespace, becomes a different //! type in each translation unit /*! This allows CEREAL_CLASS_VERSION to be safely called in a header file */ namespace{ struct version_binding_tag {}; }

So I still do not know why this is happening.

cstamatopoulos avatar Aug 16 '18 09:08 cstamatopoulos

Potentially due to non C++17 and therefore no access to "inline" keyword for variables. This is what unifies symbols across translation units (see comments in cereal.hpp). In previous versions the macro seems like it must be called from .cpp only, but the serialization definitions must be implemented there too? Im still working on it...

When I moved the version registration into the cpp files I solved my problems.

If you simply moved it to the cpp, probably you no longer get any link error because the macro is not being compiled. If you serialize the data to readable output then you could see the version used, if its 0 (default) the macro is being ignored.

dimateos avatar Mar 12 '24 14:03 dimateos