- ベストアンサー
テンプレートが複雑すぎる? 文字列比較関数を作成する方法
- 配列変数とポインタ変数の比較において、テンプレートを利用して簡単に記述する方法を模索しています。
- charとwchar_tの型を意識せずに使用することができる
- VC++2010の環境で、オーバーロードを最小限にしながらシンプルな方法はあるのか検討中です。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは。 _T()マクロやwin32apiも使用していますが、肝心なところは、compareの部分です。 (1)のcompareを呼び出す為に、compare<T, U>と書いてある部分が幾つかありますが、書かないと、(1)のcompareがコンパイルされなかったからです。 重箱の隅を突っつけば、色々と問題が出てきそうなのですが、当方はこれで精いっぱいです。取りあえずは、以下参考程度に。 #include"stdafx.h" #include<windows.h> #include<tchar.h> #include<cstring> #include<string> #include<algorithm> //---------------------------------------- //文字列のカウント(配列の場合は使用しない) //---------------------------------------- template<typename S> struct counter; //wchar_tの時 template<> struct counter<wchar_t> { static size_t size(const wchar_t* const& s) { return ::wcslen(s); } }; //charの時 template<> struct counter<char> { static size_t size(const char* const& s) { return ::strlen(s); } }; //---------------------------------------- //UNICODEへ変換(パラメータsに\0文字は含まれていない) //---------------------------------------- template<class T> struct convert; //wchar_tの時 template<> struct convert<wchar_t> { //変換の必要がないのでそのまま通す static const std::wstring get(const wchar_t* const &s, size_t sz) { return std::wstring(s, s + sz); } }; //charの時 template<> struct convert<char> { //変換する static const std::wstring get(const char* const &s, size_t sz) { const std::string mbcs(s, s + sz); const int len = ::MultiByteToWideChar(CP_ACP, 0, mbcs.c_str(), -1, NULL, 0); LPWSTR p = (LPWSTR)::malloc(len * 2); ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mbcs.c_str(), -1, p, len); const std::wstring w(p); ::free(p); return w; } }; //(1): 比較 template<typename T, typename U> int compare(const T* const &v1, size_t len1, const U* const &v2, size_t len2) { //UNICODEへ強制変換 const std::wstring lhs = convert<T>::get(v1, len1); const std::wstring rhs = convert<U>::get(v2, len2); //ここに、望む比較の仕方を実装する //例えばlstrcmpを使用する return ::lstrcmp(lhs.c_str(), rhs.c_str()); } //A: 両方ポインタ template<typename T, typename U> int compare(const T* const &v1, const U* const &v2) { return compare(v1, counter<T>::size(v1), v2, counter<U>::size(v2)); } //B1: 左がポインタ、右が配列 template<typename T, typename U, size_t L> int compare(const T* const &v1, const U(&v2)[L]) { return compare<T, U>(v1, counter<T>::size(v1), v2, L); } //C: 左が配列、右がポインタ template<typename T, typename U, size_t L> int compare(const T(&v1)[L], const U* const &v2) { return compare<T, U>(v1, L, v2, counter<U>::size(v2)); } //D: 両方配列 template<typename T, size_t L1, typename U, size_t L2> int compare(const T(&v1)[L1], const U(&v2)[L2]) { return compare<T, U>(v1, L1, v2, L2); } int main() { char aa[] = {'a', 'b', 'c'}; char *pa = "abc"; wchar_t aw[] = {_T('a'), _T('b'), _T('c')}; wchar_t *pw = _T("abc"); int result = 0; result = compare(pa, pw); result = compare(aa, pw); result = compare(pa, aw); result = compare(aa, aw); result = compare("aab", _T("b")); result = compare(_T("bcd"), _T("bc")); result = compare(aa, "c"); result = compare(aa, _T("ab")); result = compare(aw, "a"); result = compare(aw, _T("ab")); char* pka = "あいうえお"; wchar_t akw[] = {_T('あ'), _T('い'), _T('う'), _T('え'), _T('お')}; result = compare(pka, akw); result = compare(akw, pka); return 0; }
補足
回答がありがとうございます。 なるほど、左の型から右の型を求めるのではなく、右の型もテンプレート引数にしてしまえば、マッチさせることができました。 無効な型を入れた場合は、comvertにcharとwchar_tしか用意されていないため、コンパイルエラーとなるわけですね。 無理に入り口で型の制限をしないで、この方法をとってみようと思います。 比較の部分も、最終的には1つの関数にまとめられていて、簡潔でわかりやすいので、このまま利用させていただきます。 ありがとうございました。