mercredi 23 août 2017

Map Variadic Template Arguments

In the following code, I would like to finde 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 this works ok, I need to manually write the templated versions of GenericPublish__Advertise() and manually map topics[i] to publishers.

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

Aucun commentaire:

Enregistrer un commentaire