Archived

This forum has been archived. Please start a new discussion on GitHub.

Stream helper functions and C++ templates

Hi

given some struct S the slice2cpp compiler generates the stream helper functions ice_readS and ice_writeS.

Unfortunatelly this prevents using the struct S as a parameter for some template class if one wants to call those helper functions from there. What would be needed are functions in the namespace of the struct S, i.e. some S::read and S::write, either static or not.

Looking for a workaround I found two possibilities:
1) use a derived struct with wrapper functions as the template parameter.
2) use the S::__read and S::__write functions

My questions
1) Is there any reason for the helper functions not being in the namespace of the struct? Perhaps some language mapping?
2) Is it dangerous to use the inner functions __write and __read? As far as I can see at least for structs ice_writeS calls S::__write anyway.
3) Do you see any better solutions for this problem than those above?

thx in advance

regards

Comments

  • You could also create some trait classes for your ICE structs.
    template <typename T> struct ice_stream_traits {};
    
    template <S>
    struct ice_stream_traits 
    {
       static void read(const ::Ice::InputStreamPtr& stream, S& s) {
          ice_readS(stream, s);
       }
       static void write(const ::Ice::InputStreamPtr& stream, S const& s) {
          ice_writeS(stream, s);
       }
    };
    
    // then in your template code you can have
    template <typename ice_struct>
    void func(ice_struct const& foo)
    {
       // get a stream
       ice_stream_traits<ice_struct>::write(stream, foo);
    }
    
    Or something similar :)
  • oh, man

    If your solution was possible, I would not have had any problems from the begining...

    The "S" in ice_readS is _not_ substituted. (not even the preprocessor would do this. So I wonder where you got this idea from)

    This is exactly the reason why helper functions or any wrapper functions need to be in the namespace of the respective struct (and must have the same name)

    Please don't waste people's time but think in advance. At least test your suggestion.
  • I know that the S is not substituted - it is the classname you chose.

    The intention is to use template specialisation to provide a consistent interface to the ICE generated functions.

    The general template class is empty, which would mean that any ice struct that you try to use that you haven't provided a specialisation for would fail to compile.

    The template specialisation class doesn't have to be in the same namespace as the methods it calls.
  • *doh*

    Your suggestion is not less work than using derived classes. As I was expecting a better solution than mine I didn't see your intention.

    Thanks and sorry for the flame.
  • Actually, I think Tim's solution is better: if the struct is not meant to be inherited from (i.e., lacks a virtual destructor), you'll end up dealing with some undefined behaviour in your application. Furthermore, I don't think that the methods starting with "__" are meant for usage outside the ICE libraries, or generated code.
    copton wrote:
    Your suggestion is not less work than using derived classes. As I was expecting a better solution than mine I didn't see your intention.

    Thanks and sorry for the flame.
  • gasproni wrote:
    if the struct is not meant to be inherited from (i.e., lacks a virtual destructor)

    Not every inheritance needs virtual destructors - otherwise inheritance would only be possible with polymorphic types. For the case of wrapper classes I don't see the necessity for virtual destructors.

    What else do you see when warning from the struct not being meant to be inherited?

    What I meant when talking about "better" solutions is that one does not need extra effort for each new type. Concerning this, derived classes and traits are equal.
  • I think that the only way you are going to get the situation where you don't need extra typing for new types is to get slice2cpp changed.

    For the derived class solution, don't you need to construct a derived class from a base struct when the method gets the struct as a parameter? This causes a copy to be invoked.

    For a template based solution, the compiler handles the polymorphism of the types, and most likely with the inline functions will be as if you had called the longer functions themselves.

    Even given my dislike for general C style macros, given the nature of the generated functions, you could define a macro that created the template specialisation for you leaving only one line to type for each type that needed to be handled.