Archived

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

Documentation Bug and suggestion for C++ sequences

Hi ZeroC developers,

I'm relatively new to both this forum and to using ICE, but a seasoned programmer of almost 10 years in OOP languages and particularly Delphi/C++.

I was looking over another post here which deals with polymorphic sequences.

While thinking this over, I realised that the documented SLICE to C++ mappings for sequences couldn't possibly be correct.

Section 6.7.3 of the ICE user manual states:
Here is the definition of our FruitPlatter sequence from Section 4.9.3 once more:
sequence<Fruit> FruitPlatter;

The Slice compiler generates the following C++ definition for the FruitPlatter sequence:

typedef std::vector<Fruit> FruitPlatter;

Now, if Fruit is a SLICE class with at least one method, because slice2cpp translates SLICE class methods to pure virtual methods in C++. If you instantiate the template, it will generate fun expressions like "sizeof(Fruit)" in it's memory allocation code which won't compile because Fruit is abstract.

Anyhow, I ran slice2cpp (as shipped in ICE version 3.2.1) to see what typedef it actually created.

The typedef it actually generates is (after performing typedef substitution):
"typedef std::vector<IceInternal::Handle<Fruit> > FruitPlatter"

IceInternal::Handle is by the look of things a reference-counted smart pointer class, and like most smart pointer classes the * and -> operators are defined to return references and pointers.

Can I suggest the documentation be modified to explain how sequences are actually mapped to C++?

Anyhow, that typedef suggests that polymorphic sequences should work, though the syntax will be different to that in Java/C#. The elements of C++ sequences are pointers while in Java/C# the elements are effectively references. That means in Java/C# you access members with ".", and with "->" in C++.

On a secondary point, you could instead use a "smart pointer container" template similar to the one in boost (see here). What ptr_container does is similar to a vector of smart pointers, except you'd declare it as ptr_container_vector<Fruit> and the accessor methods and iterators return references instead of pointers.

ptr_container is STL-compatible and there's a pretty good chance it will become part of the STL in the future, due to a number of Boost's members also being on the ISO C++ standards committee. At any rate, I believe their licenses are compatible with yours, but I could be wrong.

IMO, that would provide the same sorts of guarantees as your smart pointer class, while retaining the more natural "." member access used in the other languages.

Unfortunately, I would guess this is one of those things that are hard to change due to backward-compatibility issues. Maybe this could be something for a major release?

Comments

  • nathanM wrote: »
    Anyhow, I ran slice2cpp (as shipped in ICE version 3.2.1) to see what typedef it actually created.

    The typedef it actually generates is (after performing typedef substitution):
    "typedef std::vector<IceInternal::Handle<Fruit> > FruitPlatter"

    IceInternal::Handle is by the look of things a reference-counted smart pointer class, and like most smart pointer classes the * and -> operators are defined to return references and pointers.

    Can I suggest the documentation be modified to explain how sequences are actually mapped to C++?

    Slice classes are always passed and manipulated via their smart pointers (see Section 6.14 in the manual). If you have a look at the demos, you will also find examples of how to use classes via their smart pointers.
    Anyhow, that typedef suggests that polymorphic sequences should work, though the syntax will be different to that in Java/C#. The elements of C++ sequences are pointers while in Java/C# the elements are effectively references. That means in Java/C# you access members with ".", and with "->" in C++.

    Polymorphic sequences do indeed work. The syntax is necessarily different in C++.
    On a secondary point, you could instead use a "smart pointer container" template similar to the one in boost (see here). What ptr_container does is similar to a vector of smart pointers, except you'd declare it as ptr_container_vector<Fruit> and the accessor methods and iterators return references instead of pointers.

    Boost would add yet another third-party dependency to Ice, which is something that we won't do light-heartedly. Also, Boost smart pointers are not quite the same as Ice smart pointers--they simply would not work.
    Unfortunately, I would guess this is one of those things that are hard to change due to backward-compatibility issues. Maybe this could be something for a major release?

    I don't think so. We'd be breaking countless programs for no good reason if were to do this.

    Cheers,

    Michi.
  • Slice classes are always passed and manipulated via their smart pointers (see Section 6.14 in the manual). If you have a look at the demos, you will also find examples of how to use classes via their smart pointers.

    Sure, I understand how reference-counted smart pointers work (I've implemented some myself), but the quoted text from section 6.7.3 gives me the impression that a sequence<T> in SLICE will wind up as a vector<T> in C++. Maybe I'm just being too literal? :).
    Polymorphic sequences do indeed work. The syntax is necessarily different in C++.

    Glad to hear it - I'm going to need it a lot :).

    And yes, I can understand why the syntax would be different - if you want to support polymorphic collections, your choices are to use either a vector of references (which won't compile due to the reference-to-reference issue in C++) or a vector to some kind of pointer.
    Boost would add yet another third-party dependency to Ice, which is something that we won't do light-heartedly. Also, Boost smart pointers are not quite the same as Ice smart pointers--they simply would not work.

    Out of curiosity, how are boost smart pointers (I assume you mean boost::shared_ptr here) and IceInternal::Handle different? They appear to have fairly similar interfaces, and both provide reference-counted semantics - what makes them mutually incompatible?

    Hm yeah, fair enough. Even barring compatibility issues, there's library versioning to think about as well.

    The idea behind boost::ptr_container was while its a container of smart pointers, its interface is defined so that you use it in the way you would use a std::vector<T&> - if it actually compiled. That would bring the syntax for using sequences in C++ into line with the other languages.
    I don't think so. We'd be breaking countless programs for no good reason if were to do this.

    Yeah, hence the remark about backward-compatability.

    I wonder, is it possible to achieve what I'm after using the ["cpp:type:"] tag in SLICE?

    I'm guessing no, since there are probably bits of the C++ ICE implementation that expect expressions like "sequence" to return something pointer-like instead of something reference-like.
  • bernard
    bernard Jupiter, FL
    IceInternal::Handle is similar to boost::intrusive_ptr. And the embedded reference count usually comes from the IceUtil::Shared base class.

    Best regards,
    Bernard
  • Bernard,

    Thanks - yes that makes sense.