0

In book "C++ Primer" fifth edition, there is a line "Entities with the same name defined in an outer scope are hidden" in the second page of Section 18.2.2. This sentence is underlined with red as follows:

enter image description here

I tried to repeat the claim in an experiment. The experimental code is as follows:

#include <cstdlib>
#include <iostream>
#include <cmath>

int abs(int n) {
    std::cout << "here" << std::endl;
    return 0; 
}

void test() {
    using std::abs;
    std::cout << abs(7) << std::endl;    
}

int main(int argc, char** argv) {
    test();

    return 0;
}

using std::abs is a using declaration, so, if the claim in "C++ Primer" is correct, the user-defined abs() function should be hidden by std::abs(). But the result is that it is the user-defined abs() function that is called. So, if the book is correct, there must be something wrong in my experiment. How do I write the experimental code to confirm the sentence in "C++ Primer"? If the book is incorrect, what should the correct exposition be that can replace the sentence? Thank you.

PS: I tried in both Windows10+VS2015 and Ubuntu 18.04+g++7.4. Both called user-defined abs() and printed out "here".

user5280911
  • 723
  • 1
  • 8
  • 21

1 Answers1

0

The book could do a better job of explaining it, but it isn't wrong. It's just that the lookup rules for overloads are somewhat more nuanced, because overloads of the same name may coexist in the same scope normally, so a using declaration mingles well with that.

If you were to indeed define a new entity that is not an overload, for instance

void test() {
    int abs = 0;
    std::cout << abs(7) << std::endl;    
}

Then that call expression would be ill-formed, because the outer callable entities are hidden by the inner int variable. The way to work around it would be with a using declaration

void test() {
    int abs = 0;
    {
      using std::abs; // Let the name refer to the functions again
      using ::abs;    // the variable abs is hidden
      std::cout << abs(7) << std::endl;    
    }
}

This experiment should illustrate what the book meant.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • Thank you for the reply. But your code still calls the user-defined abs() function, instead of std::abs(). The same is true if I commented out the `using ::abs` statement. – user5280911 Feb 09 '20 at 08:25
  • @user5280911 - I suggest you try with a conforming compiler. Clang *doesn't* call your custom overload http://coliru.stacked-crooked.com/a/e89f19eefe213cab – StoryTeller - Unslander Monica Feb 09 '20 at 08:27
  • I tried clang 6.0 just now, but the output are the same -- "here", indicating that it is the user-defined overload abs() that is called, not std::abs(). – user5280911 Feb 09 '20 at 09:06