使用BOOST_CLASS_EXPORT导出模板类,如何无需类型别名实现?
Boost序列化:模板类使用BOOST_CLASS_EXPORT无需类型别名的解决方案
问题描述
直接编写BOOST_CLASS_EXPORT(DerivedA<double, float>)时会触发编译错误,编译器认为宏BOOST_CLASS_EXPORT被传入2个参数,但该宏实际仅接受1个参数,且无法将其识别为类型。而通过定义类型别名using alias = DerivedA<double, float>; BOOST_CLASS_EXPORT(alias);可正常编译运行,现寻求无需类型别名的更简洁解决方案。
错误信息
error: macro "BOOST_CLASS_EXPORT" passed 2 arguments, but takes just 1 35 | BOOST_CLASS_EXPORT(DerivedA<double, float>) // ERROR | ^ In file included from /opt/boost-1.79.0-r7de4sm2snkkg5mu5iamq2vdfpwrloi4/include/boost/serialization/export.hpp:215: note: macro "BOOST_CLASS_EXPORT" defined here 215 | #define BOOST_CLASS_EXPORT(T) \ | /home/test/main.cc:35:1: error: ‘BOOST_CLASS_EXPORT’ does not name a type 35 | BOOST_CLASS_EXPORT(DerivedA<double, float>) // ERROR | ^~~~~~~~~~~~~~~~~~
代码示例
#include <iostream> #include <memory> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/shared_ptr.hpp> #include <boost/serialization/export.hpp> // Base class template<typename T, typename U> class Base { public: virtual ~Base() = default; template<class Archive> void serialize(Archive& ar, const unsigned int version) { // No members to serialize } }; template<typename T, typename U> class DerivedA : public Base<T, U> { public: T valueA; U valueB; DerivedA() = default; template<class Archive> void serialize(Archive& ar, const unsigned int version) { ar & boost::serialization::base_object<Base<T, U>>(*this); ar & valueA; ar & valueB; } }; BOOST_CLASS_EXPORT(DerivedA<double, float>) // ERROR // using alias = DerivedA<double, float>; // BOOST_CLASS_EXPORT(alias); // WORKS // Struct holding a shared_ptr to Base template<typename T, typename U> struct MyStruct { std::shared_ptr<Base<T, U>> ptr; template<class Archive> void serialize(Archive& ar, const unsigned int version) { ar &ptr; } }; int main() { MyStruct<double, float> original; original.ptr = std::make_shared<DerivedA<double, float>>(); // Store DerivedA return 0; }
解决方案
核心问题是C++预处理器解析宏参数时,会把尖括号内的逗号视为宏的参数分隔符,导致DerivedA<double, float>被拆成两个参数传入宏。无需类型别名的简洁解决办法是用双层括号包裹模板实例化类型:
BOOST_CLASS_EXPORT((DerivedA<double, float>))
原理说明
双层括号会让预处理器将内部的DerivedA<double, float>当作一个完整的参数整体解析,尖括号内的逗号不会被误判为宏的参数分隔符,从而匹配宏BOOST_CLASS_EXPORT(T)仅接受1个参数的定义,编译即可正常通过。
内容的提问来源于stack exchange,提问作者Mathieu
相关产品推荐
相关产品推荐

