ptr_fun(islower)がコンパイルエラー


ペン  2007-10-31 16:39:23  No: 66703

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


tetrapod  2007-10-31 17:29:44  No: 66704

無造作に 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) とする


ペン  2007-10-31 17:48:38  No: 66705

tetrapodさん、ありがとうございました。


yoh2  2007-11-01 07:47:46  No: 66706

> ・ 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))


yoh2  2007-11-01 07:55:26  No: 66707

本題とは関係ありませんがもうひとつ。
<cctype>の int islower(int) が引数に取れる値の範囲は 0 〜 MAX_CHAR と
EOF のみ (その他の値を取った時の結果は未定義) です。
もし、 string s に7ビットで収まらない文字(いわゆる全角文字とか)を入れる
可能性があり、さらに char が符号付き(VC++もgccもデフォルトではcharが
符号付きですね)だと、find_if(...)がおかしな結果になる可能性があります。
# 可能性がある、というか、現におかしくなるパターンがあります。

7ビットの範囲の文字しか扱わないなら問題ありませんが。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加