- ベストアンサー
テンプレート関数とwstring,stringの処理の違いについて
- テンプレート関数を使用して、wstringとstringに対して似たような処理を行いたい場合、Tによって値の変更が可能かどうかを調べたい。
- また、似たような処理を行いたいが、変数の型を制限する方法はあるかを知りたい。
- これらの質問についてご回答します。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
マクロで書くなら、 #define make_func(T) \ void hoge(T &s)\ {\ s=TX("a");\ } #define TX(s) s make_func(std::string); #undef TX #define TX(s) L##s make_func(std::wstring); #undef TX これがせいぜいでしょうか。
その他の回答 (6)
- D-Matsu
- ベストアンサー率45% (1080/2394)
無名名前空間というのは、その名の通り「名前のないnamespace」です。 この空間内に記述されたものは外部ファイルから事実上アクセス不能になります。名前指定できないので。 マクロで作るというのは、テンプレートを使う代わりに全部マクロで書くということです。 #define make_func(T) \ void hoge(T &s) \ { \ s = "a" \ } make_func(wstring); make_func(string); こうすると、そもそもテンプレートでないため他の型は受け付けようがない、という訳です。 尤も、見ての通り特殊化は出来てませんが。
お礼
色々テストしていて返信が遅れすみません。 これは、私のやりたいことにものすごく近いので、ものすごく惜しいですね・・・ #define make_func(T) \ #if T==char #define _TX_ #else #difine _TX_ L #endif void hoge(T &s) \ { \ s = _TX_"a" \ } みたいなこと出来ないかなーと試していたのですが、無理なようでした。 こんな感じのことは、マクロでは無理なんでしょうか?
- titokani
- ベストアンサー率19% (341/1726)
こんな感じでできますが、これだとテンプレートにする意味がないですね。 template<class T> void hoge(T &s); template<> void hoge(std::string &s) { s="a"; } template<> void hoge(std::wstring &s) { s=L"a"; } たとえば、 void init(std::string &s) { s="a"; } void init(std::wstring &s) { s=L"a"; } template<class T> void hoge(T &s) { init(s); } こんなんでどうでしょう?
お礼
うーん。それだと、関数の中で使われている全ての文字列に対して、関数を作らないといけなくなってしまいますね・・・
- machongola
- ベストアンサー率60% (434/720)
こんばんは。 template<>については、テンプレートの特殊化というものです。 http://www.geocities.jp/ky_webid/cpp/language/037.html Tにstd::stringが入れられた場合と、std::wstringが入れられた場合で、別の場所をコンパイルしているという事です。それ以外の方が入ればコンパイルエラーです。 ::については、::の前に何も書かれていなければ、そういう事になります。 http://www.geocities.jp/ky_webid/cpp/language/018.html
お礼
なるほど。よく分かりました。
- colder
- ベストアンサー率43% (30/69)
お礼
解答ありがとうございます。 これは、なかなか良さそうなソースですね。 ただ、これだと、マルチバイト文字とワイド文字を両方保持することになるので、できれば、マクロのようにコンパイル時にwchar_t用の関数とchar用の関数を生成できるのが望ましいのですが・・・ void func(){ _T_CHAR *c=_TTX_"abc"; } のようなのを、コンパイル時に別のところへコピーして貼り付けて、 #define _T_CHAR char #define _TTX_ #define _T_CHAR wchar_t #define _TTX_ L というかんじで使い分けられたら一番良いのですが、この辺りがC++の限界ということでしょうか?
- machongola
- ベストアンサー率60% (434/720)
こんばんは。 L"a"の代わりに以下のAPIで強引に変換してみては。 http://msdn.microsoft.com/ja-jp/library/cc448053.aspx 以下参考程度に。 #include<windows.h> #include<string> template<class T> struct Convert; template<> struct Convert<std::string> { //変換の必要がないのでそのまま通す static const std::string get(const std::string& mbcs) { return mbcs; } }; template<> struct Convert<std::wstring> { //LPSTRからLPWSTRへの変換 static const std::wstring get(const std::string& mbcs) { 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; } }; template<class T> void hoge(T &s) { s = Convert<T>::get("a"); } void foo(std::string &s) { ::hoge(s); } void foo(std::wstring &s) { ::hoge(s); } int main() { std::string str; ::foo(str); std::wstring wstr; ::foo(wstr); return 0; }
お礼
解答ありがとうございます。 しょうもないことですみませんが、template<>のような無記名のtemplateは初めてみたのですが、どういう意味になるのでしょうか? また、::はどういう意味で使われているのでしょうか? グローバル空間に定義されてる関数を指しているという感じの意味ですか?
- D-Matsu
- ベストアンサー率45% (1080/2394)
テンプレートでそれを実現するのは無理かと思います。 非共通部分は別々に実装し、共通部分のみテンプレートで合わせこむのがいいんじゃないでしょうか? 後者の方は、試した事はないですがテンプレートを無名名前空間内に放り込む事ができれば、外部からのアクセス遮断は行けるような気がします。 テンプレートではなくマクロで作ってしまえば固定的に展開できるので、想定外の型を入れることもできなくなりますが。
お礼
解答ありがとうございます。 >テンプレートを無名名前空間内に放り込む事ができれば 馬鹿なことを聞いてるかもしれませんが、無名名前空間に放り込むとはどのようなことを仰っているのでしょうか? >マクロで作ってしまえば固定的に展開できるので、想定外の型を入れることもできなくなりますが。 マクロで作るというのは、どのようにすることを仰ってるのでしょうか?
お礼
なるほど、これはいい感じですね。 #define make_func(T,TX) \ void hoge(T *s)\ {\ s[0]=TX##'a';\ } make_func(char,); make_func(wchar_t,L); という感じで利用してみることにします。 どうもありがとうございました。