2

I am asking this as a follow-up to this question. The previous question was asked almost three years ago, so I though asking a new one would be better.

The crux of that question I linked to is that the OP tried to run the following line of code:

find_if(s.begin(), s.end(), isalnum);

on some container s. The line of code failed to compile, and the OP should have done this

find_if(s.begin(), s.end(), ::isalnum);

The accepted answer states that there are isalnum functions in the locale and cctype libraries, and that the compiler is having trouble disambiguating between the two, hence the :: scope resolution operator. I tested it by including only one of those libraries, and the compiler is still having issues disambiguating. Why is that? If I included only one of those libraries, then obviously the compiler shouldn't "know" about the other library, so why the conflict?

The second part of my question, is how does the :: operator tell us which isalnum function we want?

Thanks

EDIT

I know that the :: operator tells us that the function/variable we want is in the global scope, but that still doesn't answer my second question.

Community
  • 1
  • 1
Konrad
  • 2,207
  • 4
  • 20
  • 31

2 Answers2

3

The isalnum from <locale> is defined in namespace std. The isalnum from <cctype> is defined in namespace std and globally, because symbols from the C library are (probably [1]) made available in global scope. Using ::isalnum requests the version of isalnum from the global scope, and not from namespace std.

[1]. The standard guarantees that if you include <ctype.h> then the symbols will be at global scope. For the C library headers, this is almost always the case for the cc* versions too, although strictly it is implementation defined.

Andrew
  • 5,212
  • 1
  • 22
  • 40
  • OK, so the symbols from the C library are available by default, even if I do not include ``? Because this compiles without including any of those two libraries. It still does not answer my question on why the compiler still has a name clash if I include only one of those. – Konrad Sep 21 '15 at 13:43
  • 1
    The symbols are not available by default, however an implementation may include standard headers from within other standard headers. – Andrew Sep 21 '15 at 13:45
  • 1
    @Andrew, _"because symbols from the C library are made available in global scope."_ Not necessarily. They might be at global scope, but they might not. It's only guaranteed if you include ``. – Jonathan Wakely Sep 21 '15 at 13:45
  • @JonathanWakely This is true. I'll modify the answer to add that caveat. – Andrew Sep 21 '15 at 13:45
  • @Andrew so you are saying that through other headers that I included, both `` and `` were included too, hence the clash? – Konrad Sep 21 '15 at 13:47
  • @KonradKapp Yes. Most likely. – Andrew Sep 21 '15 at 13:47
  • 1
    @Andrew OK, thanks. Final question: to access the function in `locale`, instead of `cctype`, what would I have had to write? I did some reading and some suggest casting the argument to a specific function pointer that matches the desired function. Is that the only way? – Konrad Sep 21 '15 at 13:59
  • 3
    No, you can also use a lambda function so overload resolution is done for the call to `alnum` : `find_if(s.begin(), s.end(), [](unsigned char c){ return std::isalnum(c); });` – Jonathan Wakely Sep 21 '15 at 14:00
  • @JonathanWakely so I assume the lambda function above will call the `cctype` version then, since it matches the `cctype` signature? – Konrad Sep 21 '15 at 14:04
  • 2
    @KonradKapp, yes. Obviously if you want to call the two-argument version in `` then you'd call it with two arguments, not one. – Jonathan Wakely Sep 21 '15 at 14:37
0

From my understanding using the scope resolution operator (::) helps identify the scope of your program.

So if you had:

Add();     //This is in Global Scope

class Test{
    void Add();       //This is in scope of the "Test" class
    int useAdd(); { ::Add();}
}

So in this case the useAdd() function refers to the add function in global scope rather than the add function within the test class. If you wanted to refer to the one in the test class using the scope resolution operator you would put Test::Add() rather than ::Add().

In the above case it may be that he had the "isalnum" function implemented both in his current class as well as a global function and he needed to specifically refer to the global function rather than the class function.

EDIT: I think I misunderstood the question, Andrew has answered it better than myself.

Vistari
  • 697
  • 9
  • 21