eclipse-cyclonedds/cyclonedds-cxx

Suggest: Use ADL(or probably better, CPO) to implement some utility types

Closed this issue · 3 comments

This is useful in some (though uncommon) use case.

For example, I'm building an app that uses CycloneDDS merely as the way to pass around variable-size raw buffer. Something like this, (not standard IDL)

module BufferType {
    template<size_t N>
    struct Buffer {
        char data[N];
    };
};

So that user can instantiate messages of different buffer size like

dds::pub::DataWriter<BufferType::Buffer<128U>> writer_buffer(publisher, topic_buffer);
dds::pub::DataWriter<BufferType::Buffer<256U>> writer_buffer(publisher, topic_buffer);

This doesn't work out of box, so I have to make some manual modifications to the auto-generated .h and .cpp file. Mostly,

  1. Add template<size_t N> to the generated message type

    template <size_t N> class Buffer {
    private:
      std::array<char, N> data_ = {};
    ...

    I also changed where this message is used in the same file.

  2. Previously, in the generated header, some static methods of TopicTraits is specialized upon the message type
    to describe the message, including getTypeName, isKeyless. But this doesn't support partially specialized
    static methods.

    So what I did was add some hidden friends inside the message class,

    template <size_t N> class Buffer {
    private:
      std::array<char, N> data_ = {};
      friend constexpr const char *getTypeName(::BufferType::Buffer<N> *) {
        return "::BufferType::Buffer<N>"; // A constexpr string manipulation is needed
                                          // to replace `N` with the actual number
      }
    
      friend constexpr bool isKeyless(::BufferType::Buffer<N> *) { return true; }
      ...

    , and change their calling site from

    org::eclipse::cyclonedds::topic::TopicTraits<TopicType>::getTypeName()

    to

    getTypeName(static_cast<T*>(nullptr))

    This works, but might not be the best way. Maybe using CPO we can do better.

I like it, I am surprised you can make this work with such small tweaks to the output of the IDL compiler :)

I do wonder if it wouldn't make more sense to treat the data as-if it were a CDR blob, because then you could use the C++ binding's serialized sample operations. (Via write_cdr and taking data into a CDRSamplesHolder.) That would also eliminate the need to have different types for different sizes. But that's just a thought.

I discussed this with my colleague today, and we believe the problem is in the design of TopicTraits. it's better to be an CPO via function. I'll see if I can come up with a PR later on that.

WRT the CDR blob, could you please provide more detail? We are open to any new methods that can solve the problem. Thank you!


I guess this echos your response in another ticket. eclipse-cyclonedds/cyclonedds#1749 (comment)

Update: We changed the code to use CDRBlob as the buffer to hold custom serialization format and it worked well. Closing this ticket now.