C++ std:any の例

C Std Any No Li



C++ プログラミングでは、標準テンプレート ライブラリ (STL) の「std::any」により、異種データを処理するための動的型付けが導入されています。従来のコンテナとは異なり、「std::any」を使用すると、任意の型の値を単一のコンテナ内に保存できるため、データ型が不明な場合や実行時に変化するシナリオでの柔軟性が向上します。この型に依存しないアプローチにより、開発者が型の安全性を維持しながら、より適応性のある表現力豊かなコードを作成できる汎用プログラミングが促進されます。この調査では、「std::any」の機能、その使用パターン、および堅牢で柔軟な C++ コードを作成する際のその役割を示す実践的な例を詳しく説明します。

例 1: Std::Any の基本的な使用法

まず、「std::any」の基本的な使用法を示す簡単な例を見てみましょう。さまざまなタイプのパラメーターを受け入れる関数が必要なシナリオを考えてみましょう。







コードスニペットは次のとおりです。



#include
#include <任意>

void processAny ( const std::any & 価値 ) {
もし ( 値.has_value ( ) ) {
std::cout << 「保存された値のタイプ:」 << 値の種類 ( ) 。名前 ( ) << std::endl;

もし ( 値の種類 ( ) == タイプID ( 整数 ) ) {
std::cout << '価値: ' << std::any_cast < 整数 > ( 価値 ) << std::endl;
} それ以外 もし ( 値の種類 ( ) == タイプID ( ダブル ) ) {
std::cout << '価値: ' << std::any_cast < ダブル > ( 価値 ) << std::endl;
} それ以外 もし ( 値の種類 ( ) == タイプID ( std::文字列 ) ) {
std::cout << '価値: ' << std::any_cast < std::文字列 > ( 価値 ) << std::endl;
} それ以外 {
std::cout << 「サポートされていないタイプです!」 << std::endl;
}
} それ以外 {
std::cout << 「std::any に値が格納されていません。」 << std::endl;
}
}

整数メイン ( ) {
プロセス任意 ( 42 ) ;
プロセス任意 ( 3.14 ) ;
プロセス任意 ( std::文字列 ( 「こんにちは、std::any!」 ) ) ;
プロセス任意 ( 4.5f ) ; // サポートされていません タイプ

戻る 0 ;
}


この例では、「std::any」参照をパラメータとして受け取り、その内容を検査する「processAny」関数を定義します。関数内では、まず has_value() を使用して、「std::any」変数に値が格納されているかどうかを確認します。値が存在する場合、type().name() を使用して格納された値のタイプを判別し、そのタイプに基づいて対応する値の出力を開始します。次に、main 関数は、整数 (42)、倍精度 (3.14)、文字列 (「Hello, std::any!」) のさまざまな型で呼び出して、「processAny」のユーティリティを示します。この関数は各タイプを適切に処理し、それぞれの値を出力します。ただし、この例ではサポートされていない浮動小数点数 (4.5f) を処理しようとすると、プログラムは型がサポートされていないことを示すことで状況を適切に処理します。



生成される出力は次のとおりです。






これは、「std::any」がどのようにさまざまなデータ型の動的な処理を可能にし、C++ での汎用プログラミングのための多用途ツールにするかを示しています。

例 2: ユーザー定義型の保存

2 番目の例では、標準テンプレート ライブラリ (STL) 内のこの動的型がカスタム データ構造にどのようにシームレスに対応するかを調べます。ユーザー定義型であるポイント構造に焦点を当て、「std::any」がそのような構造のインスタンスをどのように処理するかを紹介します。



コードは次のとおりです。

#include
#include <任意>

クラスMyClass {
公共:
私のクラス ( int値 ) : データ ( 価値 ) { }

void printData ( ) 定数 {
std::cout << 「MyClass 内のデータ:」 << データ << std::endl;
}

プライベート:
int データ;
} ;

整数メイン ( ) {
std::any anyObject = MyClass ( 42 ) ;

もし ( anyObject.has_value ( ) ) {
自動 & myClassInstance = std::any_cast < 私のクラス &> ( 任意のオブジェクト ) ;
myClassInstance.printData ( ) ;
} それ以外 {
std::cout << 「std::any に値が格納されていません。」 << std::endl;
}

戻る 0 ;
}


この C++ コード スニペットでは、「MyClass」というユーザー定義クラスでの「std::any」型の使用を示す簡単な例を作成します。クラス内には、「data」というプライベート メンバー変数と、このデータの値を表示する printData() というパブリック メソッドがあります。整数値が渡され、コンストラクターの「data」メンバーに割り当てられます。

「main」関数では、初期値 42 で「MyClass」のオブジェクトをインスタンス化し、それを「anyObject」という名前の「std::any」変数に格納します。これは、ユーザー定義クラスのインスタンスを保持する「std::any」の機能を示しています。

これに続いて、「if」ステートメントを使用して、has_value() メソッドを使用して「anyObject」に値があるかどうかを確認します。値がある場合は、「std::any_cast」を使用して格納されたオブジェクトを取得します。 「std::any_cast」は「MyClass&」テンプレート引数とともに使用され、保存されたオブジェクトを「MyClass」の参照にキャストします。次に、この参照「myClassInstance」を使用して printData() メソッドを呼び出し、「std::any」内に格納されているユーザー定義型にアクセスして操作できることを示します。

「std::any」に値が格納されていない場合は、これを意味するメッセージが出力されます。この条件チェックにより、「std::any」変数が空である可能性があるシナリオを確実に処理できます。

出力は次のとおりです。

例 3: 混合タイプのコンテナ

プログラミングにおいて、「混合型コンテナ」とは、さまざまな、潜在的に無関係なデータ型の要素を保持できるデータ構造を指します。この柔軟性は、コンパイル時にデータ型が不明な場合やプログラム実行中に動的に変化するシナリオを扱う場合に役立ちます。 C++ では、「std::any」がこの概念を例示しており、さまざまな型の値を格納する単一のコンテナーを作成できます。

さまざまなタイプを保持するコンテナーを作成するシナリオを検討してみましょう。

#include
#include <任意>
#include <ベクター>

整数メイン ( ) {

std::vector < std::任意 > 混合コンテナ;

混合コンテナ.push_back ( 42 ) ;
混合コンテナ.push_back ( 3.14 ) ;
混合コンテナ.push_back ( std::文字列 ( 'こんにちは' ) ) ;
混合コンテナ.push_back ( 真実 ) ;

のために ( 定数自動 & 要素:mixedContainer ) {
もし ( 要素の種類 ( ) == タイプID ( 整数 ) ) {
std::cout << 「整数:」 << std::any_cast < 整数 > ( 要素 ) << std::endl;
} それ以外 もし ( 要素の種類 ( ) == タイプID ( ダブル ) ) {
std::cout << 「ダブル:」 << std::any_cast < ダブル > ( 要素 ) << std::endl;
} それ以外 もし ( 要素の種類 ( ) == タイプID ( std::文字列 ) ) {
std::cout << '弦: ' << std::any_cast < std::文字列 > ( 要素 ) << std::endl;
} それ以外 もし ( 要素の種類 ( ) == タイプID ( ブール ) ) {
std::cout << 「ブール値:」 << std::any_cast < ブール > ( 要素 ) << std::endl;
} それ以外 {
std::cout << 「不明なタイプ」 << std::endl;
}
}

戻る 0 ;
}


この図では、C++ と「std::any」機能を使用した混合型コンテナーの概念を示します。 「mixedContainer」という名前の「std::vector」を作成し、さまざまなデータ型の要素を保持するコンテナとして機能します。 「push_back」関数を使用して、このコンテナに整数 (42)、倍精度 (3.14)、文字列 (「Hello」)、ブール値 (true) などのさまざまな要素を設定します。

「for」ループを使用して「mixedContainer」を反復処理する際、type() 関数を使用して各要素のデータ型を動的に識別します。 「std::any_cast」を利用して、型に基づいて対応する値を抽出して出力します。たとえば、要素の型が「int」の場合、それを整数として出力します。タイプが「double」の場合は、double として出力されます。

生成された出力は次のとおりです。

例 4: Std::Any を使用したエラー処理

「std::any」を使用する場合のエラー処理には、その型がサポートされているかどうか、または値が保存されているかどうかを確認することが含まれます。この例では、サポートされていない型を処理する方法を示します。

#include
#include <任意>

整数メイン ( ) {
std::any myAny = 42 ;

試す {

double 値 = std::any_cast < ダブル > ( 私のすべて ) ;
std::cout << '価値: ' << 価値 << std::endl;
} キャッチ ( const std::bad_any_cast & それは ) {

std::cerr << 'エラー: ' << え、何 ( ) << std::endl;
}

戻る 0 ;
}


まず、「std::any」変数「myAny」を整数型の値 42 で初期化します。後続の「try」ブロック内で、「std::any_cast」操作を使用して、この整数値を「double」にキャストする明示的な試みを行います。ただし、「myAny」に格納されている実際の型は整数であるため、このキャスト操作は「double」に対して無効であり、型の不一致が発生します。

この潜在的なエラーを適切に管理するために、「std::bad_any_cast」の特定の例外タイプをキャッチするように設計された「catch」ブロックを使用した例外処理を実装します。キャストが失敗した場合は、「catch」ブロックがアクティブになり、「std::cerr」を使用してエラー メッセージを生成し、エラーの性質を伝えます。このエラー処理戦略により、プログラムは、試行された型キャストが「std::any」変数に格納されている実際の型と衝突する状況を適切に処理できるようになります。

結論

この記事では、C++ での「std::any」のアプリケーションについて説明しました。これは、さまざまな型の値のために C++ で導入された動的型コンテナーです。基本的な使用法からユーザー定義型や異種コレクションの処理に至るまでのシナリオを紹介するさまざまな例を通じて、その多用途性を実証しました。コンパイル時にデータのタイプが不明なシナリオでの実際の応用を実証しました。さらに、エラー処理手法についても検討し、例外処理を通じてサポートされていない型を適切に管理することの重要性を強調しました。