C++プログラミング:型推論でコードをスッキリ!std::basic_string_viewと推論ガイドの使い方
テンプレートクラスである std::basic_string_view
は、コンパイラが型推論を実行できるように、推論ガイドと呼ばれる特別な機能を提供します。推論ガイドは、コンパイラが std::basic_string_view
オブジェクトの型を、引数から自動的に導出できるように支援します。
推論ガイドの利点
推論ガイドを使用すると、次の利点があります。
- テンプレートコードの汎用性の向上: 推論ガイドにより、テンプレートコードをより汎用的にすることができます。
- コンパイルエラーの削減: 型推論により、型に関するミスを防ぎ、コンパイルエラーを減らすことができます。
- コードの簡潔性: 明示的な型の指定が不要になり、コードが読みやすくなります。
推論ガイドの仕組み
std::basic_string_view
には、2つの推論ガイドがあります。
イテレータ範囲からの推論ガイド
この推論ガイドは、イテレータペアを使用して
std::basic_string_view
オブジェクトを初期化する場合に使用されます。コンパイラは、イテレータの値型からstd::basic_string_view
の要素型を推論します。例:
const char* str = "Hello, World!"; std::basic_string_view view(str, str + strlen(str));
この例では、コンパイラは
str
とstr + strlen(str)
の値型がchar
であるため、view
の型をstd::basic_string_view<char>
と推論します。レンジからの推論ガイド
std::string s = "Hello, World!"; std::basic_string_view view(s);
この例では、コンパイラは
s
の値型がchar
であるため、view
の型をstd::basic_string_view<char>
と推論します。
推論ガイドは、いくつかの制約事項があります。
- レンジは、連続範囲に対応している必要があります。
- イテレータは、サイズ付きセンチネルに対応している必要があります。
- イテレータまたはレンジは、連続している必要があります。
例 1: イテレータ範囲からの初期化
#include <string_view>
int main() {
const char* str = "Hello, World!";
// 推論ガイドを使用して std::basic_string_view<char> オブジェクトを初期化
std::basic_string_view view(str, str + strlen(str));
// view を使用して文字列を処理
for (char c : view) {
std::cout << c << " ";
}
std::cout << std::endl;
return 0;
}
この例では、std::basic_string_view<char>
オブジェクト view
が str
と str + strlen(str)
を使用して初期化されます。コンパイラは str
と str + strlen(str)
の値型が char
であるため、view
の型を自動的に推論します。
例 2: レンジからの初期化
#include <string_view>
#include <string>
int main() {
std::string s = "Hello, World!";
// 推論ガイドを使用して std::basic_string_view<char> オブジェクトを初期化
std::basic_string_view view(s);
// view を使用して文字列を処理
for (char c : view) {
std::cout << c << " ";
}
std::cout << std::endl;
return 0;
}
この例では、std::basic_string_view<char>
オブジェクト view
が s
を使用して初期化されます。コンパイラは s
の値型が char
であるため、view
の型を自動的に推論します。
#include <string_view>
int main() {
const char* str1 = "Hello, ";
const char* str2 = "World!";
// 推論ガイドは非連続イテレータをサポートしていないため、コンパイルエラーが発生
std::basic_string_view view(str1, str2);
return 0;
}
この例では、std::basic_string_view
オブジェクト view
を str1
と str2
を使用して初期化しようとします。しかし、str1
と str2
は連続していないため、コンパイラはエラーを生成します。
明示的な型指定
最も簡単な代替方法は、明示的に型を指定することです。
#include <string_view>
int main() {
const char* str = "Hello, World!";
// 明示的に型を指定して std::basic_string_view<char> オブジェクトを作成
std::basic_string_view<char> view(str, str + strlen(str));
// view を使用して文字列を処理
for (char c : view) {
std::cout << c << " ";
}
std::cout << std::endl;
return 0;
}
この例では、std::basic_string_view<char>
オブジェクト view
を明示的に型指定して作成しています。
コンストラクタの直接使用
std::basic_string_view
には、さまざまなコンストラクタが用意されています。これらのコンストラクタを使用して、明示的に型を指定せずに std::basic_string_view
オブジェクトを作成することができます。
#include <string_view>
int main() {
const char* str = "Hello, World!";
// std::basic_string_view<char> オブジェクトを直接作成
std::basic_string_view view(str);
// view を使用して文字列を処理
for (char c : view) {
std::cout << c << " ";
}
std::cout << std::endl;
return 0;
}
この例では、std::basic_string_view<char>
オブジェクト view
を std::basic_string_view
コンストラクタを使用して直接作成しています。
std::basic_string_view
以外にも、型推論をサポートするテンプレートクラスがいくつかあります。これらのクラスを使用して、std::basic_string_view
オブジェクトを作成することができます。
std::span
: C++21 で導入された、固定サイズの連続メモリ領域を表すテンプレートクラスです。std::string_view
: C++20 で導入されたstd::basic_string_view
と同様のクラスですが、std::string
オブジェクトを直接参照できます。
std::basic_string_view
推論ガイドは便利な機能ですが、制約事項があります。推論ガイドを使用できない場合、または別の方法で std::basic_string_view
オブジェクトを作成したい場合は、上記の代替方法を使用することができます。