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

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

#define RUN

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
}

#ifdef RUN
#include <cassert>
int main()
{
	const char month[][4] = {
		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
	};
	const std::size_t monthNum = sizeof(month) / sizeof(month[0]);

	char wday[][4] = {
		"Sun", "Mon", "Tue", "Web", "Thu", "Fri", "Sat"
	};
	const std::size_t wdayNum = sizeof(wday) / sizeof(wday[0]);

	char target[4];

	assert(NS::find(month, month + monthNum, "Jan") == &month[0]);
	assert(NS::find(month, month + monthNum, "XXX") == month + monthNum);

	assert(NS::find(wday, wday + wdayNum, "Sun") == &wday[0]);

	std::strcpy(target, "Feb");
	assert(NS::find(month, month + monthNum, target) == &month[1]);

	std::strcpy(target, "Mon");
	assert(NS::find(wday, wday + wdayNum, target) == &wday[1]);
}
#endif
