2011年07月28日

C++でchar[][]に対するalgorithmを実装する

この記事は以下の続きです

  1. C/C++で多次元配列を引数に取るには
  2. C/C++で多次元配列を戻り値にするには

char[][]に対するalgorithmが欲しい

C++はその標準ライブラリの一部であるSTLにて、ジェネリックプログラミングで各種処理を抽象化した関数群(algorithm)が用意されている。sortとかcountとか、for eachまで。
そして、C++(そのベースとなったC言語由来だが)で文字列は文字の配列(char[])として表現する都合上、『文字列の配列』は文字の二次元配列(char[][])として表現する事になる(std::string[]については此処では触れない)。

……じゃあ、『文字列の配列』用に特殊化したalgorithmが欲しくなるよね?

char[][]に対するstd::find()を実装する

……という訳で、char[][]用のstd::find()を実装してみた。同じようにして、wchar_t[][]用や、他のalgorithmも実装出来る筈。

#include <algorithm>
#include <functional>
#include <cstddef>
#include <cstring>

#define NS aslib
// #define NS std
// ↑ユーザー定義型用の完全特殊化以外をstd名前空間に記述するのは本当は×

namespace {
	template<typename Itr>
	Itr find_detail_for_char2darray(Itr begin, Itr end, const char *target) {
		return std::find_if(begin, end, 
			std::not1(std::bind2nd(std::ptr_fun(std::strcmp), target))
		);
	}
}

namespace NS {
	template<std::size_t N>
	const char (*find(const char (*begin)[N], const char (*end)[N], const char *target))[N] {
		return ::find_detail_for_char2darray(begin, end, target);
	}

#if NS==std
	// std下に置く場合は、以下の特殊化の定義も必要となる

	template<std::size_t N>
	char (*find(char (*begin)[N], char (*end)[N], const char *target))[N] {
		return find_detail_for_char2darray(begin, end, target);
	}

	template<std::size_t N>
	const char (*find(const char (*begin)[N], const char (*end)[N], char *target))[N] {
		return find_detail_for_char2darray(begin, end, target);
	}

	template<std::size_t N>
	char (*find(char (*begin)[N], char (*end)[N], char *target))[N] {
		return find_detail_for_char2darray(begin, end, target);
	}
#endif
}

ソースはこちら。おまけで確認用のmain()も記述している。Ideone.comにもUPしているので、そちらの方が手軽かも知れない。

ソース中でも言及しているが、本来、std名前空間下には、ユーザー定義型用に完全特殊化したもの以外は追加してはいけない事になっている(らしい)。
char[][]と同じ名前空間(上記の場合はaslib)下に、std::find()を呼び出すだけの汎用版を用意し、同じインタフェイスで使えるようにするのがスマートかも知れない。

ラベル:C++
posted by 天井冴太 at 00:38| Comment(0) | TrackBack(0) | Other | 更新情報をチェックする
この記事へのコメント
コメントを書く
コチラをクリックしてください

この記事へのトラックバック