Home > Back-end >  Boost serialization base_object unspecialized template - why does it work?
Boost serialization base_object unspecialized template - why does it work?

Time:12-04

I am trying to understand why this minimal example compiles:

https://godbolt.org/z/xYeo53GPv

template <typename T>
struct Base {
    friend class boost::serialization::access;
    template <class ARCHIVE>
    void serialize(ARCHIVE& ar, const unsigned int /*version*/) {}
};

struct Derived : public Base<int> {
    friend class boost::serialization::access;
    template <class ARCHIVE>
    void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
        ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
    }
};

Since Base is a templated type, how is it possible to pass it into BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base) without specifying the template parameters?

For reference, in Boost 1.77 that macro expands into

#define BOOST_SERIALIZATION_BASE_OBJECT_NVP(name)           \
    boost::serialization::make_nvp(                         \
        BOOST_PP_STRINGIZE(name),                           \
        boost::serialization::base_object<name >(*this)     \
    )

and boost::serialization::base_object is defined:

template<class Base, class Derived>
typename detail::base_cast<Base, Derived>::type &
base_object(Derived &d)
{
    BOOST_STATIC_ASSERT(( is_base_and_derived<Base,Derived>::value));
    BOOST_STATIC_ASSERT(! is_pointer<Derived>::value);
    typedef typename detail::base_cast<Base, Derived>::type type;
    detail::base_register<type, Derived>::invoke();
    return access::cast_reference<type, Derived>(d);
}

where Base is Base is (I think) getting explicitly substituted as Base and Derived is getting deduced as Derived.

To reiterate, how does this compile even though we are specifying the template parameters of Base?

CodePudding user response:

Indeed, it's not "unspecialized" but "unparameterized" which is actually okay because of a language feature. This mechanism is known as class name injection and is specified by the standard.

Like @康桓瑋 mentioned, the Base can be used without the template arguments within the class declaration.

For some background, see e.g.

  • Related