5

重複の可能性:
未解決のオーバーロードされた関数型 c++

以下のコード スニペットを検討してください。

#include <algorithm>
#include <cctype>
#include <string>
using namespace std;
void test(){
    std::string str = "Hello World!";
    std::transform(str.begin(), str.end(), str.begin(), tolower);
}

tolowerG++ でコンパイルするとエラーが発生します: unresolved overloaded function

using namespace std;を削除すると、コードは正常に機能します。

次に、私の質問は次のとおりです。

  • namespace stdC関数との関係は?
  • #include<ctype.h>とはどう違い#include<cctype>ますか?上記の例ではどちらも機能しませんが。
  • なぜstd::tolower機能しないのですか?std::tolowerとはどう違いtolowerますか?
4

2 に答える 2

5

namespace stdとC関数の間に関係はありません。ただし、コードはCではなくC ++であるため、C++関数も考慮する必要があります。std::tolowerたとえば、のように<locale>。あなたの問題は物事の同時発生によるものです:

  • 含めるヘッダーの1つに。が含まれます<locale>。C ++ヘッダーには、他のC ++ヘッダーを含めることができます。また、どのヘッダーに他のヘッダーが含まれるかは、実装ごとに異なる可能性があるため、作成したコードは、別のコンパイラではなく、あるコンパイラでコンパイルされる可能性があります。

  • 関数を関数引数へのポインターとして、引数がテンプレート型パラメーターである関数テンプレートに渡そうとしています。簡単に言えば、ここでオーバーロード解決を行うには tolower、コンパイラはそれを引数の型に一致させる必要があり、引数の型を知るためには、コンパイラは関数の正確な型に基づいてテンプレート型の推定を行う必要があります、過負荷解決を行った後でのみ知ることができます。

関数が必要な場合<ctype.h>(未定義の動作が発生するため、必要ありません)、インクルード <ctype.h>(グローバル名前空間に存在することを保証します)を使用::tolowerするか、オーバーロードを明示的に指定することで取得できます。たとえば、static_cast<int (*)(int)>( tolower ) (この特定のケースでstatic_castは、型変換ではなく、明示的なオーバーロード解決を意味します。)

もちろん、実際には、このようなことはしません。テキスト処理を行う場合は、必要なすべての関数を機能オブジェクトタイプとして定義します。これにより、入力をunsigned char次のように変換することで、未定義の動作を回避できます。

struct ToLower
{
    char operator()( char ch ) const
    {
        return ::tolower( static_cast<unsigned char>( ch ) );
    }
};

またはで動作する関数<locale>を使用charて:

class ToLower
{
    std::locale myLocale;   //  necessary to guarantee the lifetime of the facet.
    std::ctype const* myCType;
public:
    ToLower( std::locale const& loc = std::locale() )
        ; myLocal( loc )
        , myCType( &std::use_facet<std::ctype>( loc ) )
    {
    }

    bool operator()( char ch ) const
    {
        return myCType->tolower( ch );
    }
};

最後に、2番目の質問をWRTします。違いは、使用しているC++のバージョンとコンパイラによって異なります。ただし、グローバルには、次<ctype.h> のようになります。グローバル名前空間に関数を導入します。<cctype>それらを名前空間に導入しstd::、グローバル名前空間に導入する場合もあれば、そうでない場合もあります。(そしてあなたの3番目の質問はすでに上で答えられています:std::tolowerで定義されたオーバーロードされた関数のセットを指します;で定義さ<locale>れた単一の関数を指します、そしてあなたがやった場合を除いて、それは単にと同等です 、その場合、それは参照します上記のすべての関数のオーバーロードセットに。<cctype>::tolower<ctype.h>tolower::tolowerusing namespace std

于 2012-07-16T08:07:21.693 に答える
5

名前空間演算子を使用して、次のtolowerように C バージョンを使用できます。

::tolower(); // nothing before '::' means look in the global namespaece.

これにより、コンパイラは特定の名前空間内にない関数を探すようになります。これは、すべての C ベースの API に当てはまります。

なぜstd::tolowerうまくいかないのか、私にはわかりません。cpp 参照の例では を使用していませんstd::transform。これが理由かもしれません。

于 2012-07-16T06:23:05.387 に答える