SHOEISHA iD

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

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

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

特集記事

STL/CLRツアーガイド

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


iteratorをIEnumerable化するには...

 BCLとSTL/CLRでは要素の列挙のやり方が異なります。BCLでは一つのIEnumerablefor eachで列挙できるのに対し、STL/CLRでは要素列の先頭と末尾(の次)を指すiteratorの組が用いられます。これについてもSTL/CLRヘッダ<cliext/adapter>で定義されたrange_agdapterで二つのiteratorをIEnumerableに変換することができます。

二つのiteratorからIEnumerableを作る
#include <cliext/adapter>
#include <cliext/vector>

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

int main() {
  cliext::vector<int> iv = gcnew array<int> { 0, 1, 2, 3, 4 };
  cliext::vector<int>::iterator from = iv.begin(); ++from;
    // from は先頭の次
  cliext::vector<int>::iterator to   = iv.end();   --to;
    // to は末尾の手前
  // range_adapterで fromとtoの組をIEnumerable化する
  cliext::range_adapter<cliext::vector<int>::iterator> range(from,to);
  for each ( int item in range ) {
    Console::WriteLine(item);
  }
}
実行結果
1
2
3

 二つのiteratorからrange_adapterを生成する関数make_collectionが用意されているので、通常はこれを利用する方がお手軽でしょう。

ヘルパ関数 make_collection
#include <cliext/adapter>
#include <cliext/vector>

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

int main() {
  cliext::vector<int> iv = gcnew array<int> { 0, 1, 2, 3, 4 };
  cliext::vector<int>::iterator from = iv.begin(); ++from;
    // from は先頭の次
  cliext::vector<int>::iterator to   = iv.end();   --to;
    // to は末尾の手前
  // make_collectionで fromとtoの組をIEnumerable化する
  for each ( int item in cliext::make_collection(from,to) ) {
    Console::WriteLine(item);
  }
}

 range_adapterでiteratorをIEnumerable化することにより、アセンブリの外に対して"要素の列挙範囲"を返すことができます。

 簡単な例を紹介しましょう。名前と得点をメンバに持つExamとその集合ExamUtilを定義します。ExamUtilにはExamの追加メソッドadd、および得点の範囲を与えてその条件を満たすExamの集合を返すrangeを定義します。

STLCLR_lib.h
#ifndef STLCLR_lib_H_
#define STLCLR_lib_H_

#include <cliext/vector>

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

namespace STLCLR_lib {

  public ref class Exam {
  public:
    String^ name;  // 名前
    int     score; // 得点

    // コンストラクタ
    Exam(System::String^ n, int s) : name(n), score(s) {}

    // 比較
    static int Compare(Exam^ x, Exam^ y)
      { return x->score < y->score ?
        -1 : (y->score < x->score ? 1 : 0); }
    static bool operator<(Exam^ x, Exam^ y)
      { return Compare(x,y) < 0; }
};

  public ref class ExamUtil {
  private:
    cliext::vector<Exam^> data_;
  public:
    // Examを追加する
    void add(Exam^ e);
    // lo以上/hi未満の得点を持つExamの列挙を返す
    IEnumerable<Exam^>^ range(int lo, int hi);
  };
}

#endif

 ExamUtil::rangeではdata_が内包する要素を得点の昇順にソートし、与えられた範囲をlower_boundで検索しIEnumerableを生成します。

STLCLR_lib.cpp
#include <cliext/algorithm>
#include <cliext/adapter>

#include "STLCLR_lib.h"

namespace STLCLR_lib {

  void ExamUtil::add(Exam^ e) {
    data_.push_back(e);
  }

  IEnumerable<Exam^>^ ExamUtil::range(int lo, int hi) {
    // 得点の昇順にソートし、
    cliext::sort(data_.begin(), data_.end());
    // 与えられた範囲を示すIEnumerableを返す
    return cliext::make_collection(
        cliext::lower_bound(data_.begin(), data_.end(),
                            gcnew Exam(L"",lo)),
        cliext::lower_bound(data_.begin(), data_.end(),
                            gcnew Exam(L"",hi))
      );
  }

}

 このコード(STLCLR_lib.h/STLCLR_lib.cpp)からアセンブリを作り、C#から利用します。

STLCLR_use.cs
using System;
using STLCLR_lib;

namespace STLCLR_use {

  class Program {
    static void Main() {
      ExamUtil exam = new ExamUtil();
      exam.add(new Exam("相川", 35));
      exam.add(new Exam("井上", 20));
      exam.add(new Exam("上村", 80));
      exam.add(new Exam("江口", 50));
      exam.add(new Exam("小田", 75));
      // 30点以上/80点未満を列挙する
      foreach (Exam item in exam.range(30, 80)) {
        Console.WriteLine("{0}/{1}", item.name, item.score);
      }
    }
  }

}
実行結果
相川/35
江口/50
小田/75

まとめ

 ...いかがでしょうか、STL/CLRは単にSTLのmanaged版であるのに加え、.NET Frameworkとの親和性を考慮したいくつかの"からくり"が提供されています。.NET環境下で主力となるのはC#やVBですが、レガシーコードの利用など、managedとnativeの混在/協調にC++/CLIが利用されます。STL/CLRはC++プログラマの手に馴染んだやりかたでmanagedをサポートする強力な手駒と言えるでしょう。

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

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
特集記事連載記事一覧

もっと読む

この記事の著者

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

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」など、さまざまなカンファレンスを企画・運営しています。

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

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

メールバックナンバー