[xsd-users] xs:choice representation in C++
Boris Kolpackov
boris at codesynthesis.com
Mon Sep 28 10:11:07 EDT 2009
Hi Leonid,
Gershanovich, Leonid <leonid.gershanovich at 247realmedia.com> writes:
> I was wondering if you considered to use something like boost::variant
> (http://www.boost.org/doc/libs/1_40_0/doc/html/variant.html) for mapping
> xs:choice to c++.
Please see this post for some background on the possible choices when
mapping xs:choice (pun intended ;-)) to C++:
http://www.codesynthesis.com/pipermail/xsd-users/2007-March/000863.html
> It seems that representing following xsd construct:
> <xs:choice>
> <xs:element name="stringEl" type="xs:string"/>
> <xs:element name="intEl" type="xs:int"/>
> </xs:choice>
>
> As
> typedef string stringEl_type;
> typedef int intEl_type;
>
> boost::variant < stringEl_type , intEl_type > m_choicer;
>
> Is little cleaner in terms of expressing intended object model than
>
> optional < string > stringEl;
> optional < int > intEl;
True, though this approach will only work for some cases. Consider
the following:
<xs:choice>
<xs:element name="stringEl" type="xs:string"/>
<sequence>
<xs:element name="intEl" type="xs:int"/>
<xs:element name="boolEl" type="xs:boolean"/>
</sequence>
</xs:choice>
Now the intEl and boolEl elements becomes a single choice arm. They
should be present or absent together. To handle this with variant you
will need to wrap them into a class. In other words, you will need to
start re-creating the compositor structure via C++ classes.
Speaking of re-creating the compositor structure, we have used this
approach in XSD/e for the C++/Hybrid mapping:
http://www.codesynthesis.com/products/xsde/c++/hybrid/
For your original choice example you will get something like this:
enum choice_arm_tag
{
stringEl_tag,
intEl_tag
};
choice_arm_tag
choice_arm () const;
void
choice_arm (choice_arm_tag);
// stringEl
//
const std::string&
stringEl () const;
std::string&
stringEl ();
void
stringEl (const std::string&);
// intEl
//
int
intEl () const;
int&
intEl ();
void
intEl (int);
See Section 4.4, "Compositors" in the C++/Hybrid Mapping Getting Started
Guide for more information:
http://www.codesynthesis.com/projects/xsde/documentation/cxx/hybrid/guide/#4.4
> class my_visitor : public boost::static_visitor<int>
> {
> public:
> int operator()(intEl_type i) const
> {
> return i;
> }
>
> int operator()(const stringEl_type & str) const
> {
> return str.length();
> }
> };
>From my superficial look at boost::variant I gather that there are
two ways to extract the value: the visitor approach (which will be
way too heavy-weight for most use-cases) and the boost::get function
which doesn't really offer many advantages over what is possible now.
It sure is more awkward, thought.
BTW, if you are looking for a visitor way of traversing the object
model, have you seen the recent discussion on this topic? It starts
here:
http://www.codesynthesis.com/pipermail/xsd-users/2009-July/002391.html
Boris
More information about the xsd-users
mailing list