mercredi 23 août 2017

Two variadic templates wrapping

In a previous post, I've asked about how one can map variadic template arguments to a vector of inputs.

I have the following extended code, in which I'm trying to use two variadic templates (TSends, TReceives). They are supposed to specify a variadic list of types for a publisher and another variadic list of types for a subscriber.

I cannot seem to get it running (cannot compile). Can anyone please help?

Many thanks in advance!

#include <iostream>
#include <memory>
#include <typeinfo>
#include <vector>

class AdvertiseOptionsBase {
public:
    virtual const std::type_info &GetType() = 0;
};

template <typename TSends> 
class AdvertiseOptions : public AdvertiseOptionsBase {
public:
    AdvertiseOptions(TSends opt) : opt_(opt) {}
    const std::type_info &GetType() { return typeid(opt_); }

private:
    TSends opt_;
};

class Publisher {
public:
    Publisher(const std::string &topic) : topic_(topic) {}
    const std::string &GetTopic() const { return topic_; }
    template <typename TSends>
    void SetOptions(const AdvertiseOptions<TSends> &opt) {
        options_ = std::make_unique<AdvertiseOptions<TSends>>(opt);
    }
    const std::unique_ptr<AdvertiseOptionsBase> &GetOptions() const {
        return options_;
    }

private:
    std::string topic_;
    std::unique_ptr<AdvertiseOptionsBase> options_;
};

class Subscriber {
public:
    Subscriber(const std::string &topic) : topic_(topic) {}
    const std::string &GetTopic() const { return topic_; }
    template <typename TSends>
    void SetOptions(const AdvertiseOptions<TSends> &opt) {
        options_ = std::make_unique<AdvertiseOptions<TSends>>(opt);
    }
    const std::unique_ptr<AdvertiseOptionsBase> &GetOptions() const {
        return options_;
    }

private:
    std::string topic_;
    std::unique_ptr<AdvertiseOptionsBase> options_;
};

class Node {
public:
  template <typename TSends>
  Publisher advertise(std::string topic) {
    Publisher publisher(topic);
    TSends option;
    AdvertiseOptions<TSends> options(option);
    publisher.SetOptions<TSends>(options);
    return publisher;
  }

  template <typename TReceive>
  Subscriber subscribe(std::string topic){
    Subscriber subscriber(topic);
    TReceive option;
    AdvertiseOptions<TReceive> options(option);
    subscriber.SetOptions<TReceive>(options);
    return subscriber;
  }
};

template <typename... TSends, size_t... Is>
void GenericPublishSubscribe_AdvertiseImpl(Node &node, std::vector<Publisher> &publishers,
    const std::vector<std::string> &topics, std::index_sequence<Is...> )
{
    using swallow = int[];
    (void)swallow{0,
    (void(publishers.push_back(node.advertise<TSends>(topics.at(Is)))), 0)...
    };
}

template <typename... TSends> 
void GenericPublishSubscribe_Advertise(Node &node, std::vector<Publisher> &publishers,
                             const std::vector<std::string> &topics)
{
  GenericPublishSubscribe_AdvertiseImpl<TSends...>(node, publishers, topics,
      std::index_sequence_for<TSends...>());
}

template <typename... TReceives, size_t... Is>
void GenericPublishSubscribeSubscribeImpl(Node &node, std::vector<Publisher> &subscribers,
    const std::vector<std::string> &topics, std::index_sequence<Is...> )
{
    using swallow = int[];
    (void)swallow{0,
    (void(subscribers.push_back(node.subscribe<TReceives>(topics.at(Is)))), 0)...
    };
}

template <typename... TReceives> 
void GenericPublishSubscribeSubscribe(Node &node, std::vector<Subscriber> &subscribers,
                             const std::vector<std::string> &topics)
{
  GenericPublishSubscribeSubscribeImpl<TSends...>(node, subscribers, topics,
      std::index_sequence_for<TSends...>());
}

template < template <typename... TSends> typename TS,
           template <typename... TReceives> typename TR>
class GenericPublishSubscribe {
public:
    GenericPublishSubscribe(const std::vector<std::string> &publisher_topics, const std::vector<std::string> &subscriber_topics) {
        GenericPublishSubscribe_Advertise <TSends...>(node_, publishers_, publisher_topics);
        GenericPublishSubscribe_Subscribe <TReceives...>(node_, subscribers_, subscriber_topics);
    }
    void PrintInfo() {
        std::cout<<"Publishers:"<<std::endl<<std::endl;
        for (const auto &publisher : publishers_) {
          std::cout << publisher.GetTopic()
                    << " --> "
                    << (publisher.GetOptions()->GetType()).name()
                    << std::endl;
        }

        std::cout<<std::endl<<"Subscribers:"<<std::endl<<std::endl;
        for (const auto &subscriber : subscribers_) {
          std::cout << subscriber.GetTopic()
                    << " --> "
                    << (subscriber.GetOptions()->GetType()).name()
                    << std::endl;
        }
    }

protected:
    Node node_;
    std::vector<Publisher> publishers_;
    std::vector<Subscriber> subscribers_;
private:
};

int main() {
    std::vector<std::string> publisher_topics({"topic_int", "topic_double"});
    std::vector<std::string> subscriber_topics({"topic_char", "topic_byte"});
    GenericPublishSubscribe<<int, double>,<char, byte>> o(publisher_topics, subscriber_topics);
    o.PrintInfo();
    return 0;
}

Aucun commentaire:

Enregistrer un commentaire