Template specialization for proper linking

29 views
Skip to first unread message

Mickael Bonfill

unread,
Feb 10, 2020, 1:34:06 AM2/10/20
to cereal serialization library
I tried the Cereal library for the first time today and it seems really great.

However, I was wondering if we must create template specialization for the ::serialize(Archive & ar) method for each class we want to serialize, with all Archive possibilities?
As far as I can see, this is the only way to do if you have your classes defined into a library, then you want to call the serialization from a program with the library linked to it.

Here's an example : 

Library : 

// color.hpp
struct Color {
  Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
  {
    m_data[0] = r;
    m_data[1] = g;
    m_data[2] = b;
    m_data[3] = a;
  }
  uint8_t m_data[4];
   
 
template<class Archive>
 
void serialize(Archive & ar)
 
{
    ar
(m_data);
 
}
}

Program :

// main.cpp
#include <color.h>
#include <iostream>
#include <cereal/archives/json.hpp>

int main()
{
  cereal
::JSONOutputArchive ar(std::cout);
  ar
(Color(1,2,3,4));

  std::cout << std::endl;

}

Of course, since serialize is a template function, I receive a link error : 
Undefined symbols for architecture x86_64:
"void Color::serialize<cereal::JSONOutputArchive>(cereal::JSONOutputArchive&)", referenced from:
...

So does that mean I have to create template specialization for my hundreds of classes that need to be serialized, multiplied by the number of available Archives?


Other question completely different, but how to interpret my class Color as a primitive? I would like a JSON serialization like this : [1,2,3,4] and not {"value0", {"value1": { "value2": 1, "value3": 2, "value4": 3, "value5": 4 } }}

Thank you.


Randolph Voorhies

unread,
Mar 20, 2020, 9:10:15 AM3/20/20
to cereal serialization library
Hi Mickael,
  I just compiled your code and it worked just fine for me.  You were missing a #include <cstdint> and a semicolon at the end of your Color class, but otherwise I didn't have to change anything.

In general, as long as you're defining your templated functions in header files you should not have to specialize explicitly.

(base) rand@razorback:~/Desktop/test$ g++-9 main.cpp -I cereal-1.3.0/include/
(base) rand@razorback:~/Desktop/test$ ./a.out
{
    "value0": {
        "value0": {
            "value0": 1,
            "value1": 2,
            "value2": 3,
            "value3": 4
        }
    }

}


FYI the fixed Color.hpp:
#include <cstdint> // < Missing this include

// color.hpp
struct Color {
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
m_data[0] = r;
m_data[1] = g;
m_data[2] = b;
m_data[3] = a;
}
uint8_t m_data[4];

template<class Archive>
void serialize(Archive & ar)
{
ar(m_data);
}
}; // < Missing this semicolon
Reply all
Reply to author
Forward
0 new messages