SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

STL/CLRツアーガイド

STL/CLRの特徴と、BCLと連携するためのヘルパ関数/クラス


  • このエントリーをはてなブックマークに追加

標準C++ライブラリの構成要素の一つであるSTLとの互換性を重視したmanagedなテンプレート・ライブラリ「STL/CLR]。C++プログラマにはなじみのあるSTLの使い心地に加えて.NET FrameworkのBCL(Basic Class Library)との親和性が考慮されています。

  • このエントリーをはてなブックマークに追加

はじめに

 赤坂さんが面白いアーティクルを寄稿してくれました。

 Visual C++ 2008で新たに追加されたSTL/CLRはなんとも不思議なライブラリです。.NET FrameworkのBCL(Base Class Library)が提供するSystem.Collections.Generic名前空間で定義されたBCLコレクションと同等(それ以上?)のクラス群を提供し、それらは標準C++ライブラリに組み入れられたSTLとの高い互換性を実現しています。その代償として、templateで実装されているためにアセンブリの外に持ち出すことができません(C#やVBはtemplateを理解できませんから)。

 赤坂さんのアーティクルでは、STL/CLRコンテナがinterfaceを実装していることを利用してアセンブリ外からinterfaceとしてアクセスする方法について解説しています。

 本稿ではSTL/CLRの持つさまざまな特徴と、STL/CLRがBCLコレクションのために提供するヘルパ関数/クラスについて解説します。

STL/CLRの特徴

 と、その前に。STL/CLRを使ったコードをコンパイルすると、次のようなエラー・メッセージが現れます:

fatal error C1107: アセンブリ 'Microsoft.VisualC.STLCLR.dll' がみつ
かりませんでした: /AI または LIBPATH 環境変数を使用してアセンブリ検
索パスを指定してください。

 このエラーは、ソースコードが間接的に#includeしているヘッダ<xutility>内で#using <Microsoft.VisualC.STLCLR.dll>されており、コンパイラがアセンブリ「Microsoft.VisualC.STLCLR.dll」を見つけられなかったことに起因します。「Microsoft.VisualC.STLCLR.dll」はVC++がインストールされたディレクトリのlibサブ・ディレクトリにあるので、プロジェクト・プロパティで[#using参照の解決]に$(VCInstallDir)libを設定することでエラーを解決できます。

#using参照の解決
#using参照の解決

 さて、それではSTL/CLRにまつわるさまざまなトピックを紹介していきましょうか。

STL/CLRはSTLと同様のクラス/関数を提供する

 STL/CLRが作られた最大の目的が「C++/CLIにSTLを提供する」ことですから、これは至極当然のことです。クラス名/関数名はもちろんのこと、ヘッダ名までSTLと同じ名前が用いられています。STLと異なるのは名前空間がstdではなくcliextであること、ヘッダがcliextサブディレクトリに置かれていること、などなど。

STL(C++)だと...
#include <iostream>
#include <vector>
#include <string>

int main() {
  std::vector<std::string> sv;
  sv.push_back("zero"); // 末尾に追加
  sv.push_back("two");
  sv.push_back("THREE");
  sv.insert(sv.begin()+1, "one"); // 挿入
  sv[3] = "three"; // operator[]で3番目を更新
  sv.erase(sv.begin()+2); // iteratorの指す要素を削除
  // 全要素を列挙
  for ( std::vector<std::string>::iterator iter = sv.begin();
        iter != sv.end(); ++iter ) {
    std::cout << *iter << std::endl;
  }
  sv.clear(); // 全要素削除
  std::cout << "要素数: " << sv.size() << std::endl;
}

 このC++コードをSTL/CLRを使ってC++/CLIにポートすると次のようになります。STLとの互換性が十分考慮されているので、STLになじみのあるC++プログラマには敷居の低いライブラリに仕上がっています。

STL/CLR(C++/CLI)だと...
#include <cliext/vector>

using namespace System;

int main() {
  cliext::vector<String^> sv;
  sv.push_back(L"zero"); // 末尾に追加
  sv.push_back(L"two");
  sv.push_back(L"THREE");
  sv.insert(sv.begin()+1,L"one"); // 挿入
  sv[3] = L"three"; // operator[]で3番目を更新
  sv.erase(sv.begin()+2); // iteratorの指す要素を削除
  // 全要素を列挙
  for ( cliext::vector<String^>::iterator iter = sv.begin();
        iter != sv.end(); ++iter ) {
    Console::WriteLine(*iter);
  }
  sv.clear(); // 全要素削除
  Console::WriteLine(L"要素数: {0}", sv.size());
}

 STL/CLRコンテナの特徴の一つにメソッドの統一性があります。これもSTLとの互換性によるものです。シーケンシャルな集合から特定の要素を見つけ、そこから集合の最後までを列挙するコードを考えてみましょう。.NET FrameworkのBCLコレクション:List<T>(可変長配列)とLinkedList<T>(双方向リスト)を使ったコードはそれぞれ次のようになります。

BCLコレクション(List,LinkedList)による検索と列挙
using namespace System;
using namespace System::Collections::Generic;

bool is_three(String^ s) { return s == L"three"; }

int main() {
  array<String^>^ source = gcnew array<String^>
    { L"zero", L"one", L"two", L"three", L"four", L"five" };

  /*
   * 集合から"three"を探し、そこから最後までを列挙する
   */
  // BCLコレクション: List と LinkedList の場合:
  { // BCL List<String^>
    List<String^> container(source);
    // 何番目にあるかを調べ
    int result = container.FindIndex(
      gcnew Predicate<String^>(&is_three));
    if ( result >= 0 ) { // 見つかったら
      while ( result < container.Count ) { // そこから最後まで列挙
        Console::WriteLine(container[result]);
        ++result;
      }
    }
  }
  { // BCL LinkedList<String^>
    LinkedList<String^> container(source);
    // 目的の値を指す LinkedListNode を手にいれ、
    LinkedListNode<String^>^ result = container.Find(L"three");
    while ( result != nullptr ) { // そこから最後まで列挙
      Console::WriteLine(result->Value);
      result = result->Next;
    }
  }
}

 List<T>LinkedList<T>では要素の検索と列挙のやり方が異なっています。STL/CLRコンテナではどうでしょうか。

STL/CLRコンテナ(vector,list)による検索と列挙
#include <cliext/vector>
#include <cliext/list>
#include <cliext/algorithm>

using namespace System;
using namespace System::Collections::Generic;

bool is_three(String^ s) { return s == L"three"; }

int main() {
  array<String^>^ source = gcnew array<String^>
    { L"zero", L"one", L"two", L"three", L"four", L"five" };

  /*
   * 集合から"three"を探し、そこから最後までを列挙する
   */
  // STL/CLRコンテナ: vector と list の場合
  { // STL/CLR vector
    cliext::vector<String^> container(source);
    // 目的の値を指すイテレータを手にいれ
    cliext::vector<String^>::iterator iter =
      cliext::find(container.begin(), container.end(),
                   gcnew String(L"three"));
    while ( iter != container.end() ) { // そこから最後までを列挙
      Console::WriteLine(*iter);
      ++iter;
    }
  }
  { // STL/CLR list
    cliext::list<String^> container(source);
    // 目的の値を指すイテレータを手にいれ
    cliext::list<String^>::iterator iter =
      cliext::find(container.begin(), container.end(),
                   gcnew String(L"three"));
    while ( iter != container.end() ) { // そこから最後までを列挙
      Console::WriteLine(*iter);
      ++iter;
    }
  }
}

 vector<T>,list<T>の検索と列挙はどちらもまったく同じ書式になっていますね。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
STL/CLRコンテナの要素は3通り

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/2664 2008/07/08 06:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング