Invariant
Invariant Corporation
  
Products
OmeChron

F.A.Q.

This page contains answers to common questions handled by our support staff, along with some tips and tricks that we have found useful and presented here as questions.


Compiler says call to abs() is ambiguous, why?

Standard C++ adds overloaded versions of many of the math functions traditionally provided by <stdlib.h> and <math.h>. The header <cstdlib> provides both abs( int ) and abs( long ) (absolute value). This can result in overloading ambiguities when implicit conversions are used and <cmath> is not included. For example:

float x1, x2, y1, y2, as, at;

as = ((y2+y1)/2.0)*abs(x1-x2); // error: call to ‘abs’ ambiguous

The compiler cannot choose between the integer versions of 'abs()' and cannot find abs(float) since <cmath> is not included. {Note: this problem does not occur under MS VC++ since abs(long) is in <cmath>. }

#include <cmath>

float x1, x2, y1, y2, as, at;

as = ((y2+y1)/2.0)*abs(x1-x2); // ok: uses abs(float)

The problem can be resolved by adding "#include <cmath>".

[ Back to Top ]


Calls to vector::erase fail when using a pointer. Aren't pointers the same as iterators?

While iterators in the Standard Library share many of the same semantics as raw pointers in C++, they are not the same thing.

Given:

m_t.erase(&m_t[x]);

m_targetTag.erase(&m_targetTag[x]);

The expression '&m_t[x]' evaluates to a pointer to the element at location x. The member function ‘erase’ takes an iterator as its argument. In some implementations of the standard library (like the old HP STL), vector::iterator was defined as a raw pointer. If vector::iterator is a raw pointer, the above code compiles fine. However, there is no requirement in the Standard that vector::iterator is a raw pointer and the above code fails to compile with newer implementations of the Standard Library. Like their “C” pointer counterparts, Standard Library iterators support arithmetic expressions and can be used to correct the code and get the desired behavior as follows:

m_t.erase( m_t.begin()+x );

m_targetTag.erase( m_targetTag.begin()+x );

[ Back to Top ]


Why are there two time types in OmeChron?

There are two basic kinds of time in a simulation: relative time and absolute time. An absolute time is referenced to simulation start or a time reference e.g. GMT. Relative time is elapsed between two absolute times. If both kinds of time are represented as a simple double value, it is not possible to distinguish between them. Without type-safe use of time types, different flavors of time can be used interchangeably with potentially disastrous results. For example, suppose a model that moves the state of some system forward in time by a relative time step ‘dt’ is parameterized as follows:

class Model

{

update( double dt ); // advance the model by dt

};

The model could be erroneously updated by a caller using the 'update' function by passing in the simulation absolute time as the argument. The model state will take a giant time step instead of the small increment intended. Well defined time types can catch this kind of error at compile time. In the OmeChron simulation framework, only relative times can be converted to double and only relative times can be added to an absolute time.

The previous simulation time type provided a conversion operator to allow casting a time to a double value – this has been removed.

if( m_currentClampTime >(double)(EventSimSystem::SimClock.time() )) // error

Relative times are obtained from the global clock by calling the ‘elapsedTime’ member function.

if( m_currentClampTime > (EventSimSystem::SimClock.elapsedTime()) ) // ok

[ Back to Top ]


How can I reuse existing C++ models within OmeChron?

One approach that avoids the use of macros (remember, they are evil) is to maintain a separate, OmeChron-independent class that supports reuse through multiple in inheritance. The class relationships are shown in the UML diagram below.

UML diagram

The OmeChron class SimFloatCurve inherits from both OmeInspectable and FloatCurve. SimFloatCurve implements only the OmeChron-related functions and gets the rest of its functionality from FloatCurve. Now, FloatCurve can be reused in other applications without overhead from the OmeChron framework and without the need for macros. Note that the data members of FloatCurve that are to be used as OmeChron attributes must have protected access. Unless the member data of another class needs to be exported to OmeChron, it is often best to use containment rather than inheritance to reuse code. We have used this pattern on several occasions in the past to keep legacy codes independent of OmeChron. Caution must be observed when using multiple inheritance to avoid ambiguities that result from a base class being inherited twice [see Stroustrup 15.2.4].

[ Back to Top ]

I'm trying to use a third-party library that has class names that conflict with iTools. How can I use them without changing OmeChron?

It is unlikely that changes to OmeChron will be necessary since the iTools libraries use namespaces. For example, changing all uses of 'TArray' to 'util::TArray' should take care of naming conflicts with another library. Unless of cousre they use the same namespace name. Header name clashes can be avoided by changing your #include statements to use something like: #include "cpputil/TArray.h". Try to avoid putting #include statements in the header (.h) files as much as possible by using forward declarations as in :

class MyClass;

instead of "#include "MyClass.h"

The header file "utilfwd.h" was created with this in mind. This can greatly reduce file dependencies and compile times.

Besides the use of forward declarations, there are other ways of solving problems like this. One technique is to use a wrapper or "bridge" (see "Design Patterns" from Gamma et al). A Bridge allows the implementation to be completely isolated from an interface. The iTools IPCC Thread class is an example of a bridge we use to allow seamless switching between Win32 and Posix threads.

[ Back to Top ]

I added an algorithm to TArray from iTools. How can i get this into the next release?

The best thing to do is to avoid adding member functions to TArray<> in favor of independant template functions. Having an algorithm as a member function can cause problems when different sub-classes or instantiations of TArray<> interact. One good examle is when you need to assign one array to another. Even if they are both subclasses of TArray<T>, the assignment operator is not inherited , so you will have to go write one for the array that is assigned to. This can turn into a real pain over time. (see std::copy)

Another problem is that operator overloading does not cross scopes, so if you overload an operator for TArray<>subclass you will have to add "using" directives to bring in TArray's operators of the same name. We have been putting new algorithms in the header "TArrayAlgo.h", but you can put yours in any header you like (another advantage). Here is an example of taking a sub array with a non-member template function:

/**

*Extract a sub-array.

*/

template<class ArrayTypeIn, class ArrayTypeOut>

void sub_array( const ArrayTypeIn& array, ArrayTypeOut& sub, unsigned

rowStart, unsigned rows, unsigned colStart, unsigned cols )

{

sub.resizeTo( rows, cols );

unsigned i,j;

for( i=o; i<rows; ++i )

for( j=o; j<cols; ++j )

sub(i,j) = array(i+rowStart,j+colStart);

}//end sub_array~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Now the input and output arrays don't have to be the same type! And there is no added work in copying the result to the return value which can take a lot of CPU time.

[ Back to Top ]

When I change the size of a collection using a sizer, the collection attributes are not updated in the GUI, why?

This problem can be corrected by "tieing" the sizer attributes to the collection attribute. This is necessary for the collection attributes to be udpated as soon as the sizer changes.

Assuming you have a collection attribute:

typedef RealClctnAttr<std::vector<double> >DoubleClctnAttr;

OmeAttribute *dataAttr = new DoubleCLctnAttr( this, &a_realdata, "realdata",

"a collection of reals" );

attrs->add( dataAttr );

OmeAttribute *attr = new RealClctnSizerAttr( this, &a_realsizer, "realsize", "sizer");

You then "tie" the sizer attribute to the collection attribute:

attr->tie( dataAttr );

[ Back to Top ]

Does OmeChron support enumerated types as attributes?

The short answer is no, but OmeChron does provide a "selector" attribute that can give you similiar behavior. Selectors are designed to provide the behavior of enum's. The first step is to declare a member of your class/model that is an OmeSelector:

#include "OmeSelector.h"

class OmeSimTest: public SimModel

{

...

private:

OmeSelector a_selection;

};// end class OmeSimTest

Then you set up the option in the class/model constructor:

OmeSimTest::OmeSimTest()

{

a_selection.addOption( "Option1") ;

a_selection.addOption( "Option2") ;

a_selection.addOption( "Option3");

a_selection.setValue( "Option1"); //Set the default value

}// end constructor~~~~~~~~~~~~~~~~~~~~~~~

Then export the attribute in getAttributes:

AttribDictPtr OmeSimTest::getAttributes()

{

...

attrs->add ( new OmeSelectorAttr(this, &a_selection, "Options", "Sim Options"));

return attrs;

}//end getAttributes~~~~~~~~~~~~~~~~~~

When you inspect a Selector in the GUI, it should provide you with a pull-down selection field that displays the list of options.

To make a decision based on the selection value, just call 'value()';

if( m_selection.value() =="Option1" ) do_this();

else if( m_selection.value() =="Option2" ) do_that();

[ Back to Top ]

When I load a Windows-based SML (XML) file in linux, why do I get a "failed to load dynamic library" error?

Porting SML files runs into snag when you use version numbers for plugins. Dynamic library naming conventions for Windows® and Unix are incompatible. The quick fix is to open the file in an editor and change the name of the library. The long-term fix is not to use version numbers for plugin libraries. This can be accomplished by changing the VERSION command in the qmake '.pro' file.

First make clean in your plugin directory.

Then set the version number assignment to be empty:

VERSION=

Then run qmake and make.

Your SML files should port fine after that.

[ Back to Top ]

Why do I get compile errors in Visual C++ when using the complex number template class from the Standard Library?

Starting with version 1.4 of OmeChron, use the STLPort streams library. This will require that you build the STLPort libraries. This is relatively easy. All you do is download the latest version of STLPort and follow their install instructions. You no longer have to edit any header files or copy folders. You have to modify vcvars32.bat and your Visual Studio include directories, since the install places STLPort under "VC98/Include".

[ Back to Top ]

References

[Stroustrup] The C++ Programming Language – Special Edition. Bjarne Stroustrup. Addison-Wesley. 2000.

[Myers] Effective C++ CD. Scott Myers. Addison Wesley. 1998.
[Josuttis] The C++ Standard Library. Nicolai Josuttis. Addison Wesley. 1999.
[Gamma et al] Design Patterns. Gamma, Helm, Johnson, and Vlissides. Addison Wesley. 1995.
[Langer] Standard C++ IOStreams and Locales. Langer and Kreft. Addison Wesley. 2000.


 

OmeChron links ...

 
*

 
home | company | experience/services | products | customers | employees

Invariant Corporation, Inc.
Offices: 4035 Chris Drive, Suite F | Huntsville, Alabama 35802
Mailing Address: 4800 Whitesburg Drive #30-353 | Huntsville, AL 35802
Phone: (256) 885-9794 | Fax: (256) 881-1812
© Copyright 2007 Invariant Corporation
All Rights Reserved.

 

contact us sitemap home