In the following code, I would like to find a more generic way of calling GenericPublish__Advertise(), which takes a variadic template list. What could I do to improve it?
I would like to map topics to a publisher of a specific type:
- topic[0] -> publisher[0]
- topic[1] -> publisher[1]
- so forth
While the code works ok, I need to manually write the templated versions of GenericPublish__Advertise() and manually map topics[i] to publishers. I would like to somehow generalize the implementation of GenericPublish__Advertise().
Many thanks in advance.
Code:
#include <iostream>
#include <memory>
#include <typeinfo>
#include <vector>
class AdvertiseOptionsBase {
public:
virtual const std::type_info &GetType() = 0;
};
template <typename TSend>
class AdvertiseOptions : public AdvertiseOptionsBase {
public:
AdvertiseOptions(TSend opt) : opt_(opt) {}
const std::type_info &GetType() { return typeid(opt_); }
private:
TSend opt_;
};
class Publisher {
public:
Publisher(const std::string &topic) : topic_(topic) {}
const std::string &GetTopic() const { return topic_; }
template <typename TSend>
void SetOptions(const AdvertiseOptions<TSend> &opt) {
options_ = std::make_unique<AdvertiseOptions<TSend>>(opt);
}
const std::unique_ptr<AdvertiseOptionsBase> &GetOptions() const {
return options_;
}
private:
std::string topic_;
std::unique_ptr<AdvertiseOptionsBase> options_;
};
class Node {
public:
template <typename TSend>
Publisher advertise(std::string topic) {
Publisher publisher(topic);
TSend option;
AdvertiseOptions<TSend> options(option);
publisher.SetOptions<TSend>(options);
return publisher;
}
};
template <typename TSend1, typename TSend2>
void GenericPublish__Advertise(Node &node, std::vector<Publisher> &publishers,
const std::vector<std::string> &topics) {
publishers.push_back(node.advertise<TSend1>(topics.at(0)));
publishers.push_back(node.advertise<TSend2>(topics.at(1)));
}
template <typename TSend1, typename TSend2, typename TSend3>
void GenericPublish__Advertise(Node &node, std::vector<Publisher> &publishers,
const std::vector<std::string> &topics) {
publishers.push_back(node.advertise<TSend1>(topics.at(0)));
publishers.push_back(node.advertise<TSend2>(topics.at(1)));
publishers.push_back(node.advertise<TSend3>(topics.at(2)));
}
template <typename... TSend>
class GenericPublish {
public:
GenericPublish(const std::vector<std::string> &topics) {
GenericPublish__Advertise<TSend...>(node_, publishers_, topics);
}
void PrintInfo() {
for (const auto &publisher : publishers_) {
std::cout << publisher.GetTopic() << " -----> "
<< (publisher.GetOptions()->GetType()).name() << std::endl;
}
}
protected:
Node node_;
std::vector<Publisher> publishers_;
private:
};
int main() {
std::vector<std::string> topics({"topic_int", "topic_double"});
GenericPublish<int, double> o(topics);
o.PrintInfo();
return 0;
}