Archived

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

One-shot constructors for structs in C++ mapping

Hi,

Short version:

Introduce a metadata directive called cpp:one-shot to tell slice2cpp to create a one-shot constructor for structs.

Long version:

When default values are assigned to primitive members of a struct in slice, slice2cpp automatically creates a one-shot constructor, which makes it a lot easier to use the struct in modern C++ code (use of unnamed temporaries, also not using potentially dangerous C style initialization).

So the following slice:
module X
{
  struct Test
  {
    long l = 0;
    string s;
  };
};

allows the following code in C++:

return X::Test(1, "test");

Which is a lot more elegant and less error prone than using:
X::Test ret;
ret.value=1
ret.s = "test";
return ret;

or
X::Test ret = { 1, "test" };
return ret;

Unfortunately it's not always possible to use this trick to get that default constructor, especially in structures that do not contain any primitive data types and therefore don't support default values, e.g.
Module X
{
  sequence<long> LongSeq;
  sequence<string> StringSeq;
  struct Test
  {
    LongSeq l;
    StringSeq s; 
  };
};

Right now the only way to get a on-shot constructor is to use the class mapping, which has other severe side effects and in general different characteristics that shouldn't be used just to get this one feature. Also, in cases where there are no reasonable default values, expressing those in the slice might be misleading - especially if the only reason for assigning them is turning the struct into a non-pod with a one-shot constructor.

Therefore I would suggest the introduction of a new C++ specific metadata directive called cpp:one-shot, which tells slice2cpp to create a one-shot constructor.

So in the example above, the slice would be changed to:
Module X
{
  sequence<long> LongSeq;
  sequence<string> StringSeq;

  ["cpp:one-shot"]
  struct Test
  {
    LongSeq l;
    StringSeq s; 
  };
};

which would allow to use the following code in C++:

return X::Test(X::LongSeq(), X::StringSeq());

Obviously empty sequences are not the best example, it is even more valuable in case of structures containing other structures, e.g.

return Cart::Order(CurrencyAmount("USD", 100), CustomerFirstLast("John", "Dorian"))

The patch to accomplish this seems fairly trivial, in case you don't have the resources or don't see any commercial use of this feature I would volunteer to provide the bits necessary.

Cheers,
Michael

(the general problem has been discussed in this forum before, e.g. http://www.zeroc.com/forums/help-center/4900-c-mapping-availability-constructor-field-parameters-structs.html).

Comments

  • Patch implementing the feature

    Hi,

    Please find attached a patch that accomplishes what I proposed above.

    I specifically didn't upload it to the patch section of the forums yet, as I feel like anything ending in there should have a real chance of getting adopted - especially since this would mean a (minor) change to the slice language.

    Cheers,
    Michael
  • Not interesting?

    Since there is no feedback at all.... am I the only one who is constantly adding default values to struct members to allow one shot constructors?

    Cheers,
    Michael
  • I think this is very usable feature. Initializing structure field by field is very annoying and error prone.