Archived
This forum has been archived. Please start a new discussion on GitHub.
Sequence of 'unions'?
Is it possible to return a sequence of (simulated) union values?
I'm trying to do something along the lines of the following:
class SymValue { };
class ByteValue extends SymValue { byte byteval; };
class ShortValue extends SymValue { short shortval; };
class LongValue extends SymValue { long longval; };
class FloatValue extends SymValue { float floatval; };
class DoubleValue extends SymValue { double doubleval; };
struct SymDatum {
string name;
double rate;
short units;
SymValue* value;
};
sequence<string> SymNameSeq;
sequence<SymDatum> SymDataSeq;
// Return symbols matching 'symname'
class Source
{
nonmutating SymDataSeq SymQuery( string symname );
.
.
};
I've been having problems getting a test program for this to compile,
and just wanted to ask: is this even possible, or does the Slice-to-C++
mapping not permit such usage?
I'm trying to do something along the lines of the following:
class SymValue { };
class ByteValue extends SymValue { byte byteval; };
class ShortValue extends SymValue { short shortval; };
class LongValue extends SymValue { long longval; };
class FloatValue extends SymValue { float floatval; };
class DoubleValue extends SymValue { double doubleval; };
struct SymDatum {
string name;
double rate;
short units;
SymValue* value;
};
sequence<string> SymNameSeq;
sequence<SymDatum> SymDataSeq;
// Return symbols matching 'symname'
class Source
{
nonmutating SymDataSeq SymQuery( string symname );
.
.
};
I've been having problems getting a test program for this to compile,
and just wanted to ask: is this even possible, or does the Slice-to-C++
mapping not permit such usage?
0
Comments
-
Welcome!
That approach is definitely supported, and is the recommended way to implement a union. I suspect your compile problems stem from your use of a proxy (SymValue*) in your struct, rather than an object instance. If I'm right, you need to remove the * from the value member.
Take care,
- Mark0 -
> If I'm right, you need to remove the * from the value member.
Thanks for the help, Marc. It was a bit confusing at first, but... it
compiles as long as the right-hand of the last assignment below is a
DoubleValuePtr:
SmartNode::SymData symdata;
SmartNode::DoubleValuePtr symvalue = new SmartNode::DoubleValue;
symvalue->doubleval = 30.0;
symdata.name = "VDM:RPM";
symdata.value = symvalue; <-- this assignment
I didn't realize that the left-hand side was of type 'SymValuePtr&'
rather than 'SymValue&'.
I'm still struggling with how to access the returned values, though.
This code:
cout << "Found the following matches:\n";
for( SymDataSeq::const_iterator it = matches.begin();
it != matches.end(); ++it )
{
cout << "\t" << (*it).name << " : Type = "
<< (*it).value->ice_id() << "\n";
}
prints out:
Sending SymQuery for 'VDM:*'...
Found the following matches:
VDM:RPM : Type = ::SmartNode::DoubleValue
VDM:RATE : Type = ::SmartNode::DoubleValue
VDM:RATIO : Type = ::SmartNode::DoubleValue
Which is just as it should be. Only the *type* is SymValuePtr&, so I've
got to figure out how to convert a SymValuePtr& to a DoubleValuePtr& to
access the member I'm looking for. I'm sure I'll hit upon the proper
incantation Real Soon Now t.m. ... :-}
Thanks again,
- Dave
P.S. Ice is *great*!0 -
Originally posted by dwolfe5272
[BI'm still struggling with how to access the returned values, though.
This code:
cout << "Found the following matches:\n";
for( SymDataSeq::const_iterator it = matches.begin();
it != matches.end(); ++it )
{
cout << "\t" << (*it).name << " : Type = "
<< (*it).value->ice_id() << "\n";
}
prints out:
Sending SymQuery for 'VDM:*'...
Found the following matches:
VDM:RPM : Type = ::SmartNode::DoubleValue
VDM:RATE : Type = ::SmartNode::DoubleValue
VDM:RATIO : Type = ::SmartNode::DoubleValue
Which is just as it should be. Only the *type* is SymValuePtr&, so I've
got to figure out how to convert a SymValuePtr& to a DoubleValuePtr& to
access the member I'm looking for. I'm sure I'll hit upon the proper
incantation Real Soon Now t.m. ... :-}[/b]
You need to use a dynamic cast:for( SymDataSeq::const_iterator it = matches.begin(); it != matches.end(); ++it ) { DoubleValuePtr p = DoubleValuePtr::dynamicCast(*it); if (p) { cout << p->doubleVal << "\n"; } }
See page 190 in the manual.
Cheers,
Michi.P.S. Ice is *great*!
Glad you like it!0 -
You need to use a dynamic cast...
See page 190 in the manual.
Thanks for the pointer--it just saved me a lot of time. I was trying to
commit all sorts of horrible atrocities with dynamic_cast<> and C-style
casts. I even attempted to call a (thankfully, non-existent) function
called DoubleValue::checkedCast()--d'oh! :-% It's really quite nice,
actually, that such rude hacks failed to compile! That seems to be a
real strength of Ice: it seems to be kind of hard to do something really
wrong and have the code compile properly.
Thinks are working much, much better now... :-D0 -
Originally posted by dwolfe5272
I was trying to commit all sorts of horrible atrocities with dynamic_cast<> and C-style casts. I even attempted to call a (thankfully, non-existent) function called DoubleValue::checkedCast()--d'oh! :-%
Yes, I would definitely call that a "horrible atrocity." Maximum penalty: writing insurance broking applications in BASIC and COBOL for five years
When using Ice, you never need to use a cast. If you want to do something and find that you can do it only with a cast, it is a sure-fire sign that you doing something you had better notIt's really quite nice, actually, that such rude hacks failed to compile! That seems to be a real strength of Ice: it seems to be kind of hard to do something really wrong and have the code compile properly.
Yes. A well-designed mapping uses the type system as a safety net: by carefully creating compatible and incompatible types as necessary, a lot of errors can be caught at compile time. This really is the main advantage of strongly-typed languages. Unfortunately, poor design (especially in C++) often ends up weakening the type system instead of strengthening it; C++ with its user-defined conversions unfortunately provides a lot of rope to hang yourself with. (The CORBA C++ mapping is a great example for how to unintentionally shoot holes through the static type system.)
Cheers,
Michi.0 -
Originally posted by michi
When using Ice, you never need to use a cast.
Clarification: what I meant by this is that you never need to use a static_cast, reinterpret_cast, or a sledgehammer cast. But, of course, to get from a base to a derived, you have to use a dynamicCast.
Cheers,
Michi.0