Skip to content

Instantly share code, notes, and snippets.

@wjwwood
Created August 10, 2018 20:09
Show Gist options
  • Save wjwwood/7c8bcdc4f7a57633a754c7678d4b06b3 to your computer and use it in GitHub Desktop.
Save wjwwood/7c8bcdc4f7a57633a754c7678d4b06b3 to your computer and use it in GitHub Desktop.
example of policy based design for rosbag storage interface
#include <string>
#include <vector>
struct SerializedMessage
{
// ...
};
class RosbagIOStorageInterface
{
public:
virtual
const char *
get_open_flags() = 0;
};
class RosbagReadStorageInterface : public RosbagIOStorageInterface
{
public:
virtual
SerializedMessage
read_next_message();
virtual
std::vector<std::string>
list_topics();
const char *
get_open_flags() override {return "r";}
// ...
};
class RosbagWriteStorageInterface : public RosbagIOStorageInterface
{
public:
virtual
void
add_topic(const std::string & topic_name/*, ... */);
virtual
void
write_message(const SerializedMessage & serialized_message_instance);
const char *
get_open_flags() override {return "a+";}
};
class RosbagReadWriteStorageInterface
: public RosbagReadStorageInterface,
public RosbagWriteStorageInterface
{
public:
const char *
get_open_flags() override {return RosbagWriteStorageInterface::get_open_flags();}
};
template<typename IOInterfaceT>
class RosbagStorageInterface : public IOInterfaceT
{
public:
RosbagStorageInterface()
{
static_assert(
std::is_base_of<RosbagIOStorageInterface, IOInterfaceT>::value,
"Must use a class based on RosbagIOStorageInterface with RosbagStorageInterface");
}
virtual
bool
open(const std::string & bag_uri)
{
(void)bag_uri;
const char * open_flags = this->get_open_flags();
(void)open_flags;
return true;
}
};
void
look_at_bag(RosbagReadStorageInterface * ro_bag_interface)
{
ro_bag_interface->read_next_message();
}
void
add_to_bag(RosbagWriteStorageInterface * wo_bag_interface)
{
wo_bag_interface->write_message(SerializedMessage());
}
void
rewrite_bag(RosbagReadWriteStorageInterface * rw_bag_interface)
{
rw_bag_interface->write_message(rw_bag_interface->read_next_message());
}
int main()
{
RosbagStorageInterface<RosbagReadStorageInterface> ro_interface;
ro_interface.open("foo");
ro_interface.read_next_message();
// compile error:
// no member named 'write_message' in 'RosbagStorageInterface<RosbagReadStorageInterface>'
// ro_interface.write_message(SerializedMessage());
look_at_bag(&ro_interface);
// compile error:
// no matching function for call to 'add_to_bag'
// add_to_bag(&ro_interface);
// compile error:
// no matching function for call to 'rewrite_bag'
// rewrite_bag(&ro_interface);
RosbagStorageInterface<RosbagWriteStorageInterface> wo_interface; // is this necessary?
wo_interface.open("foo");
// compile error:
// no member named 'read_next_message' in 'RosbagStorageInterface<RosbagWriteStorageInterface>'
// wo_interface.read_next_message();
wo_interface.write_message(SerializedMessage());
// compile error:
// no matching function for call to 'look_at_bag'
// look_at_bag(&wo_interface);
add_to_bag(&wo_interface);
// compile error:
// no matching function for call to 'rewrite_bag'
// rewrite_bag(&wo_interface);
RosbagStorageInterface<RosbagReadWriteStorageInterface> rw_interface;
rw_interface.open("foo");
rw_interface.read_next_message();
rw_interface.write_message(SerializedMessage());
look_at_bag(&rw_interface);
add_to_bag(&rw_interface);
rewrite_bag(&rw_interface);
// compile error:
// base specifier must name a class
// RosbagStorageInterface<float> wont_compile;
// compile error:
// Must use a class based on RosbagIOStorageInterface with RosbagStorageInterface
// RosbagStorageInterface<std::string> wont_either;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment