template<typename T>
struct is_message : std::false_type {};
template<typename T>
class Publisher {
static_assert(is_message<T>::value, "This message type is not supported");
public:
void Publish(T& msg) {}
};
之前的代码是来自第三方库的简化草图(ROS2 很简陋,我们不应该更改此代码库), 它使用类型特征
is_message
将消息类型限制为其生成的 IDL C++ 消息,该消息生成代码来专门化先前的类型特征模板,如下所示:
class GeneratedIdlMessageX {
public:
};
template<> struct is_message<GeneratedIdlMessageX> : std::true_type {};
然后用户可以像这样删除正在工作的发布者:
#include <ros2_headers.h>
#include <ros2idl_generated_message.h>
Publisher<GeneratedIdlMessageX> publisher;
现在的问题是我们也想支持 protobuf 消息,但我们无法修改 protobuf IDL 代码生成来添加此专门化。 因此,我们必须在每个 protobuf 消息发布声明上手动添加此专业化,如下所示:
#include <ros2_headers.h>
#inlcude <protobuf_generated_message.h>
template<> struct is_message<ProtoBufMessageY> : std::true_type {};
Publisher<ProtoBufMessageY> publisher;
怎样才能省掉这个烦人的工作呢?
一个直接的想法是引入一个预定义的通用标头,它将所有 protobuf 生成的消息专门用于发布者用户。 考虑到所有protobuf生成的c++消息都是从
MessageLite
继承的,我尝试直接专门化基类,显然它不起作用:
// of course this won't work
template <> struct is_message<protobuf::MessageLite> : std::true_type{};
现在我因为无法修改第三方(ros2)和 protobuf IDL 生成代码而陷入困境,感谢任何帮助
template <std::derived_from<protobuf::MessageLite> T>
struct is_message<T> : std::true_type {};