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 スタイルの null 終端文字列を使用してフィールドの値を設定します。これを呼び出した後、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 ベースのインデックスにある要素を返します。[0, foo_size()-1]
の範囲外のインデックスでこのメソッドを呼び出すと、未定義の動作になります。void set_foo(int index, ::absl::string_view value)
: 指定された 0 ベースのインデックスにある要素の値を設定します。void set_foo(int index, const string& value)
: 指定された 0 ベースのインデックスにある要素の値を設定します。void set_foo(int index, string&& value)
: 渡された文字列から移動して、指定された 0 ベースのインデックスにある要素の値を設定します。void set_foo(int index, const char* value)
: C スタイルの null 終端文字列を使用して、指定された 0 ベースのインデックスにある要素の値を設定します。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 スタイルの null 終端文字列を使用して、新しい要素をフィールドの末尾に追加します。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 スタイルの null 終端文字列からコピーします。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 Foo {
VALUE_A = 0;
VALUE_B = 5;
VALUE_C = 1234;
}
プロトコルバッファコンパイラは、Foo
列挙型に加えて、標準の 生成コードに加えて、次の新しい関数を生成します。
::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)
に切り替わります。