String View API
std::stringを使用するC++文字列フィールドAPIは、内部のprotobuf実装とその進化を著しく制約します。例えば、mutable_string_field()はstd::string*を返し、フィールドを格納するためにstd::stringを使用することを強制します。これにより、アリーナとの相互作用が複雑になり、文字列ペイロードの割り当てがアリーナからかヒープからかを追跡するためにアリーナの寄付状態を維持する必要があります。
長期的には、すべてのランタイムAPIと生成されたAPIがstring_viewを入力として受け入れ、アクセサから返すように移行したいと考えています。このドキュメントは、30.xリリース時点での移行状況を説明します。
文字列フィールドアクセサ
エディション2023の一部として、string_type機能はVIEWオプションと共にリリースされ、生成されたstring_view APIへの段階的な移行を可能にしました。この機能を使用すると、stringおよびbytesフィールドのC++生成コードに影響します。
ctypeとの相互作用
エディション2023では、フィールドレベルでctypeを指定できますが、ファイルレベルまたはフィールドレベルでstring_typeを指定できます。同じフィールドで両方を指定することはできません。ファイルレベルでstring_typeが設定されている場合、フィールドで指定されたctypeが優先されます。
VIEWオプションを除いて、string_typeのすべての可能な値は、同じように綴られ、同じ動作をする対応するctype値を持っています。例えば、両方の列挙型にCORD値があります。
エディション2024以降では、ctypeを指定することはできなくなります。
生成された単数形フィールド
エディション2023でのこれらのフィールド定義のいずれかの場合
bytes foo = 1 [features.(pb.cpp).string_type=VIEW];
string foo = 1 [features.(pb.cpp).string_type=VIEW];
コンパイラは以下のアクセサメソッドを生成します
::absl::string_view foo() const: フィールドの現在の値を返します。フィールドが設定されていない場合、デフォルト値を返します。void clear_foo(): フィールドの値をクリアします。これを呼び出した後、foo()はデフォルト値を返します。bool has_foo(): フィールドが設定されている場合、trueを返します。void set_foo(::absl::string_view value): フィールドの値を設定します。これを呼び出した後、has_foo()はtrueを返し、foo()はvalueのコピーを返します。void set_foo(const string& value): フィールドの値を設定します。これを呼び出した後、has_foo()はtrueを返し、foo()はvalueのコピーを返します。void set_foo(string&& value): 渡された文字列から移動して、フィールドの値を設定します。これを呼び出した後、has_foo()はtrueを返し、foo()はvalueを返します。void set_foo(const char* value): Cスタイルのヌル終端文字列を使用してフィールドの値を設定します。これを呼び出した後、has_foo()はtrueを返し、foo()はvalueのコピーを返します。
生成された繰り返しフィールド
これらのフィールド定義のいずれかの場合
repeated string foo = 1 [features.(pb.cpp).string_type=VIEW];
repeated bytes foo = 1 [features.(pb.cpp).string_type=VIEW];
コンパイラは以下のアクセサメソッドを生成します
int foo_size() const: フィールドに現在含まれている要素の数を返します。::absl::string_view foo(int index) const: 指定されたゼロベースのインデックスにある要素を返します。[0, foo_size()-1]の範囲外のインデックスでこのメソッドを呼び出すと、未定義の動作になります。void set_foo(int index, ::absl::string_view value): 指定されたゼロベースのインデックスにある要素の値を設定します。void set_foo(int index, const string& value): 指定されたゼロベースのインデックスにある要素の値を設定します。void set_foo(int index, string&& value): 渡された文字列から移動して、指定されたゼロベースのインデックスにある要素の値を設定します。void set_foo(int index, const char* value): Cスタイルのヌル終端文字列を使用して、指定されたゼロベースのインデックスにある要素の値を設定します。void add_foo(::absl::string_view value): 指定された値で新しい要素をフィールドの末尾に追加します。void add_foo(const string& value): 指定された値で新しい要素をフィールドの末尾に追加します。void add_foo(string&& value): 渡された文字列から移動して、新しい要素をフィールドの末尾に追加します。void add_foo(const char* value): Cスタイルのヌル終端文字列を使用して、新しい要素をフィールドの末尾に追加します。void clear_foo(): フィールドからすべての要素を削除します。これを呼び出した後、foo_size()はゼロを返します。const RepeatedPtrField<string>& foo() const: フィールドの要素を格納する基になるRepeatedPtrFieldを返します。このコンテナクラスは、STLライクなイテレータやその他のメソッドを提供します。RepeatedPtrField<string>* mutable_foo(): フィールドの要素を格納する基になる変更可能なRepeatedPtrFieldへのポインタを返します。このコンテナクラスは、STLライクなイテレータやその他のメソッドを提供します。
生成されたOneofフィールド
これらのいずれかのoneofフィールド定義の場合
oneof example_name {
string foo = 1 [features.(pb.cpp).string_type=VIEW];
...
}
oneof example_name {
bytes foo = 1 [features.(pb.cpp).string_type=VIEW];
...
}
コンパイラは以下のアクセサメソッドを生成します
bool has_foo() const: oneofケースがkFooの場合、trueを返します。::absl::string_view foo() const: oneofケースがkFooの場合、フィールドの現在の値を返します。それ以外の場合、デフォルト値を返します。void set_foo(::absl::string_view value):- 同じoneof内の他のoneofフィールドが設定されている場合、
clear_example_name()が呼び出されます。 - このフィールドの値を設定し、oneofケースを
kFooに設定します。 has_foo()はtrueを返し、foo()はvalueのコピーを返し、example_name_case()はkFooを返します。
- 同じoneof内の他のoneofフィールドが設定されている場合、
void set_foo(const string& value): 最初のset_foo()と同様ですが、const string参照からコピーします。void set_foo(string&& value): 最初のset_foo()と同様ですが、渡された文字列から移動します。void set_foo(const char* value): 最初のset_foo()と同様ですが、Cスタイルのヌル終端文字列からコピーします。void clear_foo():- oneofケースが
kFooでない場合、何も変更されません。 - oneofケースが
kFooの場合、フィールドを解放し、oneofケースをクリアします。has_foo()はfalseを返し、foo()はデフォルト値を返し、example_name_case()はEXAMPLE_NAME_NOT_SETを返します。
- oneofケースが
列挙型名ヘルパー
エディション2024以降、新しい機能enum_name_uses_string_viewが導入され、デフォルトでtrueになります。無効にしない限り、次のようなenumの場合
enum Foo {
VALUE_A = 0;
VALUE_B = 5;
VALUE_C = 1234;
}
プロトコルバッファコンパイラは、Foo enumに加えて、標準の生成コードに加えて、次の新しい関数を生成します。
::absl::string_view Foo_Name(int value): 指定された数値の名称を返します。そのような値が存在しない場合、空の文字列を返します。複数の値がこの数を持つ場合、最初に定義されたものが返されます。上記の例では、Foo_Name(5)はVALUE_Bを返します。
これは、次のような機能オーバーライドを追加することで、以前の動作に戻すことができます。
enum Foo {
option features.(pb.cpp).enum_name_uses_string_view = false;
VALUE_A = 0;
VALUE_B = 5;
VALUE_C = 1234;
}
この場合、名前ヘルパーはconst string& Foo_Name(int value)に戻ります。