-2

I have a replica of what's inside my code

#include <utility>
using namespace std;

class Parent
{
    public:
        void swap(Parent*);
};
class A : public Parent 
{
    public:
        void handle();
};


void A::handle()
{

    long x = 1;
    long y = 2;
    swap(x,y);
}


int main()
{
    A v;
    v.handle();
    return 0;
}

The error log:

main.cpp: In member function 'void A::handle()':
main.cpp:21:10: error: no matching function for call to 'A::swap(long int&, long int&)'
  swap(x,y);
          ^
main.cpp:7:8: note: candidate: void Parent::swap(Parent*)
   void swap(Parent*);
        ^
main.cpp:7:8: note:   candidate expects 1 argument, 2 provided

To my understanding swap call inside A::handle() will trigger non-qualified lookup and because it will find swap name in the parent class that's a function, argument-dependent name lookup (ADL) will be called. Why the ADL here can't find the std::swap and use it ? Instead it tries to call the Parent's swap.

What I am missing here ?


Platform/Compiler: Red hat 6.7/ GNU 5.3.0

Platform/Compiler: Windows 10/ visual studio 2015

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Shady Atef
  • 2,121
  • 1
  • 22
  • 40
  • 1
    ADL does not work with fundamental types. `long` is not from `std::` – 463035818_is_not_an_ai Aug 04 '21 at 12:11
  • 1
    Regarding the error: Do you _have_ an overload matching `A::swap(long int&, long int&)`? – Ted Lyngmo Aug 04 '21 at 12:11
  • 1
    Firstly, the compiler looks in the closest containing scope (in this case, `A` and then its bases, before looking in the global scope) for the name. It finds `Parent::swap()`. Then, due to the hiding rule, this hides candidate `swap()` functions in containing scopes. All this happens before it attempts to determine if arguments match types for the candidates it finds. To resolve, either call `std::swap()` unambiguously (i.e. `std::swap(x,y)` instead of `swap(x,y)`) or remove `Parent::swap()`. – Peter Aug 04 '21 at 12:12
  • @TedLyngmo, No. This all the code I have. – Shady Atef Aug 04 '21 at 12:12
  • @ShadyAtef But, you see that the compiler is trying to match against it. That's a huge hint! – Ted Lyngmo Aug 04 '21 at 12:13
  • @TedLyngmo, I see this, I am trying to understand the ADL related part. I understand I can use fully-qualified call to `std::swap`. – Shady Atef Aug 04 '21 at 12:15
  • How do you expect a function that takes a `Parent *` as its only argument to be called with two `long` values? – Sam Varshavchik Aug 04 '21 at 12:17
  • @ShadyAtef Doesn't any of the answers provide info enough? (edit: oh, only one answer is left - it's good though) – Ted Lyngmo Aug 04 '21 at 12:17
  • @TedLyngmo, Ofcourse a lot of answers are here, but I was trying to wrap my head around it. Yeah, a sole answer, he is lucky gaining a good reputation points. Thank you for your time – Shady Atef Aug 04 '21 at 12:25
  • @ShadyAtef Thanks and I'm glad you found a solution to the problem! – Ted Lyngmo Aug 04 '21 at 12:26
  • 2
    I voted to reopen this question because it's intentional and reproducible. – songyuanyao Aug 04 '21 at 12:50
  • @Peter "*To resolve, either call `std::swap()` unambiguously (i.e. `std::swap(x,y)` instead of `swap(x,y)`) or remove `Parent::swap()`*" - 3rd option, add `using std::swap;` inside of `void A::handle()` , then `swap(x,y);` will use `std::swap()` if `Parent::swap()` is not a match for the arguments. [demo](https://ideone.com/a34DhB) – Remy Lebeau Aug 04 '21 at 17:09

1 Answers1

7

For unqualified name lookup:

name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

So the name swap is examined in class A firstly, it's not found, then examined in class Parent, it's found, then name lookup stops. std::swap introduced into global scope won't be found at all.

And

Why the ADL here can't find the std::swap and use it ?

You're passing longs to swap, while ADL works with class types, but not fundamental types.

  1. For arguments of fundamental type, the associated set of namespaces and classes is empty

BTW: In this special case even you change to pass some class types defined in std namespace to swap ADL won't be considered either.

First, the argument-dependent lookup is not considered if the lookup set produced by usual unqualified lookup contains any of the following:

  1. a declaration of a class member

Parent::swap is a class member which is found by usual unqualified name lookup, ADL still won't be considered.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405