13.1.25.2 Insertion into Any

To allow a value to be set in an any in a type-safe fashion, the following overloaded operator function is provided for each separate OMG IDL type T:

// C++
void operator<<=(Any&, T);

This function signature suffices for the following types, which are usually passed by value:

  • Short, UShort, Long, ULong, Float, Double
  • Enumerations
  • Unbounded strings (char* passed by value)
  • Object references (T_ptr)

For values of type T that are too large to be passed by value efficiently, two forms of the insertion function are provided:

// C++
void operator<<=(Any&, const T&);      // copying form
void operator<<=(Any&, T*);           // non-copying form

The copying form is largely equivalent to the first form shown, as far as the caller is concerned.

These “left-shift-assign” operators are used to insert a typed value into an any, as follows:

// C++
Long value = 42;
Any a;
a <<= value;

In this case, the version of operator<<= overloaded for type Long sets both the value and the TypeCode properly for the Any variable.

Setting a value in an any using operator<<= means the following:

  • For the copying version of operator<<=, the lifetime of the value in the Any is independent of the lifetime of the value passed to operator<<=. The implementation of the Any does not store its value as a reference or a pointer to the value passed to operator<<=.
  • For the noncopying version of operator<<=, the inserted T* is consumed by the Any. The caller may not use the T* to access the pointed-to data after insertion because the Any assumes ownership of T*, and the Any may immediately copy the pointed-to data and destroy the original.
  • With both the copying and noncopying versions ofoperator<<=, any previous value held by the Any is properly deallocated. For example, if the Any(TypeCode_ptr,void*,TRUE) constructor (described in Handling Untyped Values) were called to create the Any, the Any is responsible for deallocating the memory pointed to by the void* before copying the new value.

Copying insertion of a string type causes the following function to be invoked:

// C++
void operator<<=(Any&, const char*);

Since all string types are mapped to char*, this insertion function assumes that the value being inserted is an unbounded string. Distinguishing Boolean, Octet, Char, and Bounded Strings describes how bounded strings may be correctly inserted into an Any. Noncopying insertion of both bounded and unbounded strings can be achieved using the Any::from_string helper type described in Distinguishing Boolean, Octet, Char, and Bounded Strings.

Type-safe insertion of arrays uses the Array_forany types described in Arrays. The ORB provides a version of operator<<= overloaded for each Array_forany type. For example:

// IDL
typedef long LongArray[4][5];

// C++
typedef Long LongArray[4][5];
typedef Long LongArray_slice[5];
class LongArray_forany { ... };

void operator<<=(Any &, const LongArray_forany &);

The Array_forany types are always passed to operator<<= by reference to const.The nocopy flag in the Array_forany constructor is used to control whether the inserted value is copied (nocopy == FALSE) or consumed (nocopy == TRUE). Because the nocopy flag defaults to FALSE, copying insertion is the default.

Because of the type ambiguity between an array of T and a T*, it is highly recommended that portable code explicitly use the appropriate Array_forany type when inserting an array into an Any. For example:

// IDL
struct S {... };
typedef S SA[5];
// C++
struct S { ... };
typedef S SA[5];
typedef S SA_slice;
class SA_forany { ... };
SA s;
// ...initialize s...
Any a;
a <<= s;                    // line 1
a <<= SA_forany(s);        // line 2

Line 1 results in the invocation of the noncopying operator<<=(Any&, S*) due to the decay of the SA array type into a pointer to its first element, rather than the invocation of the copying SA_forany insertion operator. Line 2 explicitly constructs the SA_forany type and thus results in the desired insertion operator being invoked.

The noncopying version of operator<<= for object references takes the address of the T_ptr type, as follows:

// IDL
interface T { ... };
// C++
void operator<<=(Any&, T_ptr);              // copying
void operator<<=(Any&, T_ptr*);      // non-copying

The noncopying object reference insertion consumes the object reference pointed to by T_ptr*; therefore, after insertion the caller may not access the object referred to by T_ptr because the Any may have duplicated and then immediately released the original object reference. The caller maintains ownership of the storage for the T_ptr itself.

The copying version of operator<<= is also supported on the Any_var type.