We're updating the issue view to help you get more done. 

Allow Formattable to wrap user-defined objects

Description

The Formattable class currently assumes the contained object is an instance of the Measure class:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // NOTE: As of 3.0, there are limitations to the UObject API. It does // not (yet) support cloning, operator=, nor operator==. To // work around this, I implement some simple inlines here. Later // these can be modified or removed. [alan] // NOTE: These inlines assume that all fObjects are in fact instances // of the Measure class, which is true as of 3.0. [alan] // Return TRUE if *a == *b. static inline UBool objectEquals(const UObject* a, const UObject* b) { // LATER: return *a == *b; return *((const Measure*) a) == *((const Measure*) b); } // Return a clone of *a. static inline UObject* objectClone(const UObject* a) { // LATER: return a->clone(); return ((const Measure*) a)->clone(); }

This causes an exception to be thrown when a users tries to wrap their own custom UObject-derived object in a Formattable. The current workaround is to make the custom type inherit from Measure instead of UObject.

The comment in the code above suggests cloning that support may be added to UObject in future, and the UObject documentation says:

The clone() function is not available in UObject because it is not implemented by all ICU classes. Many ICU services provide a clone() function for their class trees, defined on the service's C++ base class, and all subclasses within that service class tree return a pointer to the service base class (which itself is a subclass of UObject). This is because some compilers do not support covariant (same-as-this) return types; cast to the appropriate subclass if necessary.

It's now 2018 and compilers have had support for covariant return types for at least 14 years. If we can add clone() to UObject, we can remove the Measure-casting hacks in Formattable. I imagine it could be a lot of work to add cloning support to all the ICU classes that don't already implement it, so perhaps it's acceptable for the base implementation to throw an exception to indicate cloning is not supported.

Alternatively we could limit the impact by only adding the clone() method to the relevant class tree (as described in the UObject documentation above), i.e. create a new class with a name of FormattableObject (or perhaps CloneableObject). This would however require the below public methods to be deprecated and new ones created to use the new type instead of UObject:

  • Formattable (UObject *objectToAdopt)

  • const UObject * getObject () const

  • void adoptObject (UObject *objectToAdopt)

Status

Assignee

Markus Scherer

Time Needed

Days

Components

Fix versions

Priority

assess