c++serializationeigencereal

What is happenning in this template header?


There is an amazingly useful answer on how to serialize eigen matrices using cereal: Serializing Eigen::Matrix using Cereal library

I copied and verified this code works, but I am having a hard time understanding what is going on in the header:

template <class Archive, class _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols> inline
typename std::enable_if<traits::is_output_serializable<BinaryData<_Scalar>, Archive>::value, void>::type
save(Archive & ar, Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> const & m)
{
    int32_t rows = m.rows();
    int32_t cols = m.cols();
    ar(rows);
    ar(cols);
    ar(binary_data(m.data(), rows * cols * sizeof(_Scalar)));
}

The first line is taking a cereal archive type and then all the needed eigen template parameters.

I am not 100% sure what the second line is doing, it seems to be declaring the run type? But I can't follow what the type is mean to be.

Additionally (if possible, but not required for an answer)

Why does this not work? (it doesn't I checked, it won't compile):



template <class Archive>
void serialize( Archive& archive, Eigen::Vector2f& vec )
{
    archive(
        CEREAL_NVP((float&)vec[0]),
        CEREAL_NVP((float&)vec[1])
    );
}

template <class Archive>
void serialize( Archive& archive, Eigen::Vector3f& vec )
{
    archive(
        CEREAL_NVP((float&)vec[0]),
        CEREAL_NVP((float&)vec[1]),
        CEREAL_NVP((float&)vec[2])
    );
}

Solution

  • The template uses SFINAE (Substitution Failure Is Not An Error) to limit the template parameters this function takes.

    Basically if the compiler considers the function signature of the template function to be erroneous, it simply ignores this function instead of producing a compiler error.

    typename std::enable_if<traits::is_output_serializable<BinaryData<_Scalar>, Archive>::value, void>::type
    

    is effectively void, if traits::is_output_serializable<BinaryData<_Scalar>, Archive>::value evaluates to true and it results in an erroneous signature, if it evaluates to false.