Boost 序列化 base_object 非专用模板 - 为什么它有效?

Boost serialization base_object unspecialized template - why does it work?

我试图理解为什么这个最小的例子可以编译:

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);
    }
};

既然Base是一个模板化的类型,如何在不指定模板参数的情况下将它传递给BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base)

供参考,在 Boost 1.77 中该宏扩展为

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

boost::serialization::base_object定义为:

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);
}

其中 BaseBase(我认为)被明确替换为 Base 并且 Derived 被推断为 Derived.

重申一下,即使我们指定了 Base 的模板参数,这又如何编译?

的确,它不是“非专业化”而是“非参数化”,由于语言特性,这实际上是可以的。这种机制被称为 class name injection 并由标准指定。

就像@康桐薇提到的,Base 可以在 class 声明中没有模板参数的情况下使用。

对于一些背景,请参阅例如