Re: Removal of string-based object resolution

Posted by Luigi Ballabio-2 on
URL: http://quantlib.414.s1.nabble.com/Removal-of-string-based-object-resolution-tp3371p3372.html

On 2004.10.11 14:45, Andre Louw wrote:
> I notice that all the string-based object resolution have been removed
> from the SWIG wrapper files (calendars, currencies, daycounters). Is  
> there an alternative mechanism that I'm missing to resolve specific
> implementations of these classes based on an input string?

Andre,
        you can add the following in the .i file:

%extend Calendar {
    Calendar(const std::string& name) {
        if (name == "USA") return new Calendar(UnitedStates());
        else if ....
    }
}

to get back the old behavior. If you're worried about performance, you can  
tailor the above to your usage by checking first the calendars you use most  
frequently.


> Without this mechanism I would have to resolve this in Python, which I'm  
> assuming "off the cuff" would have a performance impact?

In principle, but I don't think it would matter much if you, say, create a  
Calendar, pass it to a Schedule, build a bond and price it---the creation  
overhead should be negligible compared to the work done later. Also, see  
below.


> If there is no alternative, any objections to reworking this to include
> all the latest implementations?

Well, on the one hand I was trying to remove redundancy and have one less  
thing to maintain. On the other hand, one might want to customize the  
strings used---because, say, his database uses different names, or he wants  
'USA' to mean the Bond market calendar rather than the Stock exchange, and  
that is more difficult if I write _my_ strings in stone--or in the  
wrappers, which is practically the same thing.  I'd suggest storing a few  
calendar instances in a Python dictionary when one loads the module, as in:

my_calendars = {
    'USA': UnitedStates(),
    'TARGET': TARGET(),
    ...
}

and use my_calendars[name] instead of Calendar(name). Or you can even  
write:

def _init_calendar(self,name):
    self.this = my_calendars[name]
    self.thisown = 0
Calendar.__init__ = _init_calendar

and keep using Calendar(name). This might actually improve performance, as  
you would get a reference to an already created calendar instead of  
allocating new memory in order to create one (*).


Later,
        Luigi


(*) technical note: the wrapper code could not be written simply as

if (name == "USA")  return new UnitedStates;

as the pointer would have been cast to Calendar* and later deleted as such.  
Since the Calendar class has no virtual destructor, the above would be  
undefined behavior according to the C++ standard. Instead, the code had to  
be written as:

if (name == "USA")  return new Calendar(UnitedStates());

i.e., an initialization, an allocation with new, and a copy---inefficient,  
and just plain twisted.