ptr_fun(islower)がコンパイルエラーになるのですが、どう修正したらよいですか?
#include <algorithm>
#include <cctype>
#include <functional>
#include <iostream>
using namespace std;
int my_islower(char c) {
return islower(c);
}
int main() {
string s = "abc";
find_if(s.begin(), s.end(), ptr_fun(islower)); // コンパイルエラー
find_if(s.begin(), s.end(), ptr_fun(my_islower)); // 問題なし
}
//コンパイルエラーメッセージ:
//error: no matching function for call to `ptr_fun(<unknown type>)'
g++ 3.4.4 cygwin
無造作に using namespace std; を使っているのが原因
gcc-3.4.4 では islower は std 中に存在する template function になっている。
using namespace std; して ptr_fun(islower) だと
自動的に std::ptr_fun(std::islower) となってしまい
template<typename charT> inline bool islower(charT c, const locale& l) { ... }
の template 類推が不可能になってしまうから。
解決策は2つ
・ using namespace std; をやめる (推奨)
・ using namespace std; を残したいなら ptr_fun(::islower) とする
tetrapodさん、ありがとうございました。
> ・ using namespace std; を残したいなら ptr_fun(::islower) とする
<cctype>のインクルードで、グローバル名前空間に int islower(int) が
導入される保証はなかったように思います。
今回の例では確かに::islowerが導入されているようですけれど、たまたまでは?
確実にグローバル名前空間に入れたいなら、<cctype>ではなく、<ctype.h>の
インクルードが必要ではないでしょうか。でもあまり推奨したくないなぁ。
今回のエラーは、
- islower は、<cctype>の1引数版と<locale>の2引数版(こっちはテンプレート)
がある。
- ptr_fun も、1引数の関数へのポインタを取るものと、2引数の関数へのポインタ
を取る2種類の関数テンプレートがオーバーロードされている。
というところに原因があるのですから、使用するislowerかptr_funのどちらかの種類を
確定させるとよいと思います。
・使用するptr_funを確定:
ptr_funのテンプレート引数を明示的に指定して、ptr_funの引数の型を確定させる。
std::ptr_fun<int, int>(std::islower)
・使用するislowerを確定:
&islowerを int(*)(int) (または islower を int(&)(int)) に
static_castして、使用するislowerを確定させる。
std::ptr_fun(static_cast<int (*)(int)>(&std::islower))
本題とは関係ありませんがもうひとつ。
<cctype>の int islower(int) が引数に取れる値の範囲は 0 〜 MAX_CHAR と
EOF のみ (その他の値を取った時の結果は未定義) です。
もし、 string s に7ビットで収まらない文字(いわゆる全角文字とか)を入れる
可能性があり、さらに char が符号付き(VC++もgccもデフォルトではcharが
符号付きですね)だと、find_if(...)がおかしな結果になる可能性があります。
# 可能性がある、というか、現におかしくなるパターンがあります。
7ビットの範囲の文字しか扱わないなら問題ありませんが。
ツイート | ![]() |