Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

namespace in C++ when using c function [duplicate]

Tags:

c++

c

namespaces

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

There is an error about tolower when compiling with G++: unresolved overloaded function.

If using namespace std; is removed, 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 don't work in the example above.
  • Why std::tolower also doesn't work? What's the difference between std::tolower and tolower?
like image 969
Martin Wang Avatar asked Jul 16 '12 06:07

Martin Wang


People also ask

Does C have using namespace?

Namespace is a feature added in C++ and is not present in C. A namespace is a declarative region that provides a scope to the identifiers (names of functions, variables or other user-defined data types) inside it.

Why namespace is not used in C?

The problem with putting using namespace in the header files of your classes is that it forces anyone who wants to use your classes (by including your header files) to also be 'using' (i.e. seeing everything in) those other namespaces.

What functions are in namespace std?

The using directive using namespace std makes names within namespace std candidates for matching names used in the current scope. The name vector exists within namespace std (as a templated class).

What are inside the namespace std in C++?

A namespace is a declarative region that provides a scope to the identifiers (the names of types, functions, variables, etc) inside it. Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries.


1 Answers

There is no relationship between namespace std and C functions. But your code isn't C, it's C++, so you also have to consider C++ functions. Like std::tolower, for example, in <locale>. Your problem is due to a concurrence of things:

  • One of the headers you include includes <locale>. C++ headers are allowed to include other C++ headers, and which header includes which other header may vary from one implementation to the other, so the code you've written might compile with one compiler, and not with another.

  • You're trying to pass the function as a pointer to function argument, to a function template where the argument is a template type parameter. Simply put, in order to do overload resolution on tolower here, the compiler must match it to the type of the argument, and in order to know the type of the argument, the compiler must do template type deduction based on the exact type of the function, which it can only know once it has done overload resolution.

If you want the function in <ctype.h> (which you don't, since it would result in undefined behavior), you can get it either by including <ctype.h> (which guarantees that it is present in the global namespace) and using ::tolower, or by explicitly specifying the overload you want, e.g. static_cast<int (*)(int)>( tolower ) (In this particular case, static_cast doesn't mean type conversion, but explicit overload resolution.)

In practice, of course, you don't do this sort of thing. If you're doing any text processing at all, you'll define all of the necessary functions as functional object types, which avoid undefined behavior by either converting the input to unsigned char:

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

or by using the functions in <locale> which do 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 your second question: the difference depends on the version of C++ you're using and the compiler. Globally, however: <ctype.h> will introduce the functions into the global namespace; <cctype> will introduce them into the namespace std::, and maybe (or maybe not) into the global namespace. (And your third question has already been answered above: std::tolower refers to a set of overloaded functions defined in <locale> and <cctype>; ::tolower refers to a single function defined in <ctype.h>, and just tolower is the equivalent of ::tolower, unless you've done using namespace std, in which case, it will refer to the overload set of all of the functions mentionned above.

like image 136
James Kanze Avatar answered Oct 09 '22 13:10

James Kanze