ReactiveX / RxCpp

Reactive Extensions for C++
Apache License 2.0
3.03k stars 390 forks source link

Inheritance and runtime polymorphism. #505

Open renantarouco opened 5 years ago

renantarouco commented 5 years ago

Hi! I know issues is not the best place for asking any technical doubts. But in this matter I've searched everywhere e tried lots of approaches to solve my problem that is: I am writing a custom operator to serialize Protobuf messages to json. The Protobuf's API has a helper method to do that and it uses inheritance polymorphism to do so:

std::function<observable<protobuf::Message*>(observable<std::string>)> proto_to_json() {
  google::protobuf::util::JsonOptions opt;
  opt.always_print_primitive_fields = true;
  std::string jstr;
  google::protobuf::util::MessageToJsonString(referee, &jstr, opt);
  return jstr;
}

(I'm used to shared_ptr, but this was my first attempt to just test the functionality.) Sounds like a good place to start. But when I attempt to compile, an error issuing the type of my function raises. I have the following code in my main function:


int main() {
  // Constructing an object to receive datagrams in the group_ip, port and buffer_max_size
  MulticastReceiver mr("224.5.23.1", 10003, 4096);
  auto ref_stream = mr.datagram$() | // a std::string observable with received datagram - ok
    parse_referee() | // parses string to a shraed_ptr<SSL_Referee> proto message - ok
    proto_to_json(); // compile error
}

I omitted the rest of the code for brevity. I also tried using a different approach with runtime polymorphism writing a type _json_serializablet to encapsulate the method _tojson and also a static method _tojson(cont T&), then I write my own implementation of _tojson with a const reference to SSL_Referee:

template<typename T>
std::string to_json(const T& x) {}
class json_serializable_t {
  public:
    template<typename T>
    json_serializable_t(T x) : self_(std::make_shared<model<T>>(std::move(x))) {}
    friend std::string to_json(const json_serializable_t& x)
    { return x.self_->to_json_(); }
  private:
    struct concept_t {
      virtual ~concept_t() = default;
      virtual std::string to_json_() const = 0;
    };
    template<typename T>
    struct model final : concept_t {
      model(T x) : data_(std::move(x)) {}
      std::string to_json_() const override
      { return to_json(data_); }
      T data_;
    };
    sptr<const concept_t> self_;
};

And then:

std::string to_json(const SSL_Referee& referee) {
  google::protobuf::util::JsonOptions opt;
  opt.always_print_primitive_fields = true;
  std::string jstr;
  google::protobuf::util::MessageToJsonString(referee, &jstr, opt);
  return jstr;
}

std::function<observable<std::string>(std::shared_ptr<json_serializable_t>)> serialize_to_json() {
  return [](observable<std::shared_ptr<json_serializable_t>> object$) {
    return object$ |
      operators::map([](std::shared_ptr<json_serializable_t> object) { 
        return to_json(*object); }); };
}

Any of those approaches give me the following error with different signatures:

main.cc:46:21: error: no match for ‘operator|’ (operand types are ‘rxcpp::observable<std::shared_ptr<SSL_Referee>, rxcpp::dynamic_observable<std::shared_ptr<SSL_Referee> > >’ and ‘std::function<rxcpp::observable<std::__cxx11::basic_string<char> >(rxcpp::observable<std::shared_ptr<furgbol::models::json_serializable_t> >)>’)
   observable<sptr<SSL_Referee>> referee$ = ref_mr.datagram() |
                                            ~~~~~~~~~~~~~~~~~~~
     parse_referee() |
     ~~~~~~~~~~~~~~~~^
     serialize_to_json();

Then am stuck at this for like two weeks and still didn't find any helpful material to help me with that (although I've learned a lot of other things on the way, whats a very good thing). The only thing that I didn't tried yet was writing something to use with the lift operator, which I can't find much about but saw an example that looked like could implement what I'm trying.

Well I apologize for any spelling errors and atrocities with the C++ usage, although it's one of my favorite languages and I am really engaged into learning everything as possible. Also it's the first time I'm writing anything on the web, even to ask something, in a large community like that. Am I giving to little information? Or (already know the answer) asking in the wrong place? But anything will help even if it is to learn to behave in the community. :smiley: Thank you for your time.