c++xsdtemplatestypescodesynthesis

C++ types using CodeSynthesis XSD Tree Mapping


I'm using CodeSynthesis XSD C++/Tree Mapping utility to convert an existing xsd into c++ code we can populate the values in. This was we always make sure we follow the schema.

After doing the conversion, I'm trying to get it to work so I can test it. Problem is, I'm not used to doing this in c++ and it's my first time with this tool.

I start with a class called ABSTRACTNETWORKMODEL with types versno_type and fromtime_type typedef'd inside. Here is the constructor I am trying to use as well as the typedefs

ABSTRACTNETWORKMODEL(const versno_type&, const fromtime_type&);
typedef ::xml_schema::double_ versno_type;
typedef ::xml_schema::time fromtime_type;

all these are in the ABSTRACTNETWORKMODEL class and the definitions for double_ and time are:

typedef ::xsd::cxx::tree::time<char, simple_type> time;
typedef double double_;

where the definition for time is a class with multiple constructors:

template<typename C, typename B>
class time: public B, public time_zone
{
  public:
  time(unsigned short hours, unsigned short minutes, double seconds);
  ...
}

I know I'm not correctly creating a new ABSTRACTNETWORKMODEL but I don't know what I need to do this. Here is all I'm trying to do at this point:

  ::xml_schema::time t();
  ABSTRACTNETWORKMODEL anm(1234, t);

This, of course, throws an error about converting the second parameter, but can somebody tell me what it is that is incorrect? Or at least point me down the right path, as one of the things I'm trying to do right now is learn more c++.


Solution

  • I've been bitten by this before. If the line:

    ::xml_schema::time t();
    

    is exactly as it appears in your code (that is, with the parens) then the problem is that you didn't actually instantiate an object like you think.

    To instantiate an object you would use

    ::xml_schema::time t;
    

    The first line, instead, declares a function t() that takes no arguments and returns an object of type ::xml_schema::time. Since there is no body, the compiler thinks you will define the function later. It is perfectly legal C++, and it's something that people do a lot (say, in header files) so the compiler accepts it, does not issue a warning because it has no way of knowing that's not what you meant, and does something you weren't expecting.

    And when you pass that function to the ABSTRACTNETWORKMODEL constructor you get an error because you can't pass a function as an argument (you can pass a pointer to the function, and you can call the function, passing the resulting temporary):

    ::xml_schema::time t();
    ABSTRACTNETWORKMODEL anm(1234, t()); // calls t(), gets a temporary of type ::xml_schema::time, and passes the temporary to the constructor
    

    So the reason "the instantiation of time didn't cause an error" is that a time object was never instantiated. The time class doesn't have a default constructor either, and attempting to instantiate t with the correct syntax would have thrown the error you were expecting.

    For the record, the parenthesis are required in some cases. For instance, when instantiating a temporary object and manipulating that temporary in the same line:

    int hours = time().get_hours(); // assuming that there is now a default constructor
    

    Because dropping the first set of parenthesis will result in an error:

    int hours = time.set_time("12:00:00am"); // error: there is a time class, but no object named "time"
    

    Believe me, I really like C++, but the syntax can get really difficult to keep straight some times.