13.1.25.2 Anyへの挿入

型保障の方法でanyの値を設定できるようにするために、OMG IDLの型Tごとに次のオーバーロード演算子関数が個別に用意されています:

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

この関数シグネチャは、通常値渡しされる次の型には十分です:

  • ShortUShortLongULongFloatDouble
  • 列挙
  • 無制限文字列(値によって渡されるchar*)
  • オブジェクト参照(T_ptr)

型Tの値が大きすぎて完全に値を渡すことができない場合、次の2つの形式の挿入関数が用意されています:

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

コピー形式は、呼出し側に関して見ると、最初に示した形式とほぼ同じです。

前述の左シフト代入演算子は、次のように型付き値をanyに挿入するために使用します:

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

この場合、型Longにオーバーロードされたoperator<<=のバージョンは、Any変数の値とTypeCodeの両方を適切に設定します。

operator<<=を使用してanyの値を設定することは、次のことを意味します:

  • operator<<=のコピー・バージョンの場合、Anyの値の存続期間は、operator<<=に渡された値の存続期間に依存しません。Anyの実装では、operator<<=に渡された値への参照またはポインタとして、その値を格納しません。
  • operator<<=の非コピー・バージョンの場合、挿入されたT*はAnyが処理します。呼出し側は挿入後にT*を使用してポイントされたデータにアクセスすることはできません。これは、AnyがT*の所有権を得たため、ポイントされたデータをAnyがただちにコピーして元のデータを破棄する可能性があるためです。
  • operator<<=のコピーと非コピーの両バージョンでは、Anyが保持していた前の値がすべて適切に割当て解除されます。たとえば、「型付けされていない値の処理」で説明したAny(TypeCode_ptr,void*,TRUE)コンストラクタを呼び出してAnyを作成した場合、Anyvoid*が指すメモリーの割当てを解除してから、新しい値をコピーします。

文字列型の挿入をコピーすると、次の関数が呼び出されます:

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

文字列型はすべてchar*にマッピングされるので、この挿入関数は、挿入された値が無制限文字列であることを想定します。制限付き文字列を正しくAnyに挿入する方法については、「Boolean、Octet、Char、および制限付き文字列の識別」を参照してください。制限付き文字列と無制限文字列の挿入をコピーせずに実行するには、Any::from_stringヘルパー型を使用します。このヘルパー型については、「Boolean、Octet、Char、および制限付き文字列の識別」を参照してください。

型保障で配列を挿入するには、「配列」で説明しているArray_forany型を使用します。ORBでは、Array_forany型ごとに、オーバーロードされたoperator<<=のバージョンが用意されています。例:

// 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 &);

Array_forany型は、常にconstを参照してoperator<<=に渡されます。Array_foranyコンストラクタのnocopyフラグは、挿入された値をコピー(nocopy == FALSE)するか、消費(nocopy == TRUE)するかを制御するために使用されます。nocopyフラグはデフォルトでFALSEに指定されているため、デフォルトでは挿入がコピーされます。

Tの配列とT*には型にあいまいさがあるため、移植性のあるコードの場合は、配列をAnyに挿入するときに適切なArray_forany型を明示的に使用することをお薦めします。例:

// 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

行1の場合、配列型SAがその最初の要素へのポインタに集束されるため、コピーSA_forany挿入演算子ではなく、非コピーoperator<<=(Any&, S*)が呼び出されます。行2の場合、SA_forany型が明示的に作成されるので、目的の挿入演算子が呼び出されます。

オブジェクト参照のoperator<<=の非コピー・バージョンでは、次のようにT_ptr型のアドレスを取得します:

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

非コピーのオブジェクト参照の挿入では、T_ptr*が指すオブジェクト参照を処理します。そのため、挿入後、呼出し側はT_ptrによって参照されるオブジェクトにアクセスできない可能性があります。これは、Anyが元のオブジェクト参照を複製してただちに解放している可能性があるためです。呼出し側は、T_ptr自体のストレージの所有権を保持します。

operator<<=のコピー・バージョンは、Any_var型でもサポートされます。