C ++ namespace when using c function

Possible duplicate:
unresolved overloaded function type C ++

Consider the code snippet below:

#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); } 

When compiling with g ++, a tolower error occurs: an unresolved overloaded function .

If using namespace std; deleted, the code works fine.

Then my questions are:

  • What is the relationship between namespace std with C functions?
  • What is the difference between #include<ctype.h> and #include<cctype> ? Although both of them do not work in the above example.
  • Why doesn't std::tolower either? What is the difference between std::tolower and tolower ?
+4
source share
2 answers

There is no connection between namespace std and C functions. But your code is not C, it is C ++, so you also need to consider C ++ functions. For example, std::tolower , for example, in <locale> . Your problem is related to the coincidence of things:

  • One of the included headers includes <locale> . C ++ headers are allowed to include other C ++ headers, and which header includes a different header may vary from one implementation to another, so the code you wrote can compile with one compiler, and not with another.

  • You are trying to pass a function as a pointer to a function argument, to a function template, where the argument is the type of the parameter parameter. Simply put, in order to enable overload resolution on a tolower here, the compiler must match it with the type of the argument, and in order to find out the type of the argument, the compiler must infer the type of the template based on the exact type of the function that it can only know after it made overload permission.

If you need a function in <ctype.h> (which you will not do, since it leads to undefined behavior), you can either get it by including <ctype.h> (which ensures that it is present in the global namespace) and using ::tolower , or explicitly specifying the overload you want, for example. static_cast<int (*)(int)>( tolower ) (In this particular case, static_cast does not mean type conversion, but explicit overload resolution.)

In practice, of course, you do not. If you are doing any kind of text processing at all, you will define all necessary as functional types of objects that avoid undefined behavior or convert an input to an unsigned char :

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

or using functions from <locale> that work with 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 ); } }; 

Finally, WRT is your second question: the difference depends on the version of C ++ used and the compiler. Globally: <ctype.h> present functions in the global namespace; <cctype> will enter them in the std:: and possibly (or maybe not) in the global namespace. (And your third question is already higher: std::tolower refers to a set of overloaded functions defined in <locale> and <cctype> ; ::tolower refers to one function defined in <ctype.h> , and just tolower is equivalent to ::tolower , if you did not use using namespace std , in which case, it will refer to the set of overloads of all the functions mentioned above.

+4
source

You can use the namespace operator to use the C tolower version as follows:

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

This will force the compiler to look for a function that is not within a specific namespace, which is the case for all C-based APIs.

As for why std::tolower doesn't work, I have no idea. The cpp link example does not use std::transform , this may be the reason.

+3
source

All Articles