43

I was trying to learn and adopt the copy-swap idiom following this thorough explanation on this question: the Copy-Swap Idiom.

But I found some code I had never seen: using std::swap; // allow ADL in this example

class dumb_array
{
public:
    // ...

    void swap(dumb_array& pOther) // nothrow
    {
        using std::swap; // allow ADL    /* <===== THE LINE I DONT UNDERSTAND */

        swap(mSize, pOther.mSize); // with the internal members swapped,
        swap(mArray, pOther.mArray); // *this and pOther are effectively swapped
    }
};
  1. what does using std::swap; mean inside the body of a function implementation ?
  2. what does ADL mean ?
Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
  • 2
    [MSalter's answer](http://stackoverflow.com/a/4782809/464581) is IMHO clearly the better more comprehensive answer, since he explains about ADL (which is the whole reason for doing the `using` here). I think you should select that as solution. – Cheers and hth. - Alf Feb 19 '17 at 01:00

3 Answers3

84

This mechanism is normally used in templated code, i.e. template <typename Value> class Foo.

Now the question is which swap to use. std::swap<Value> will work, but it might not be ideal. There's a good chance that there's a better overload of swap for type Value, but in which namespace would that be? It's almost certainly not in std:: (since that's illegal), but quite likely in the namespace of Value. Likely, but far from certain.

In that case, swap(myValue, anotherValue) will get you the "best" swap possible. Argument Dependent Lookup will find any swap in the namespace where Value came from. Otherwise the using directive kicks in, and std::swap<Value> will be instantiated and used.

In your code, mSize is likely an integral type, and mArray a pointer. Neither has an associated namespace, and std::swap is with 99.9% certainty optimal for them anyway. Therefore, the using std::swap; declaration seems useless here.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 7
    I believe that it is quite legal to provide specializations of standard templated functions inside the `std` namespace. §17.4.3.1/1 "A program may add template specializations for any standard library template to namespace std. Such a specialization (complete or partial) of a standard library template results in undefined behavior unless the declaration depends on a user-defined name of external linkage and unless the specialization meets the standard library requirements for the original template" That said, it is not common to implement `swap` specializations in the `std` namespace. – David Rodríguez - dribeas Jan 24 '11 at 15:33
  • 10
    @dribeas: indeed it's legal to specialize `std::swap`, and if in doubt about your users, you should probably specialize `std::swap` *and* provide a `swap` in your own namespace to be found by ADL. But there are limits to specializing `std::swap`, the killer one being that you can't *partially* specialize it, because it's a function template, and so if you've written a class template (like a new container), you can't specialize `std::swap` for it, and hence you have to take the ADL route. MSalters is correct in what he says, though: you can't overload `std::swap`, only specialize. – Steve Jessop Jan 24 '11 at 15:56
14

The using keyword has scoped effect.

This means that std::swap can be referred to as swap during the scope of the using keyword.

Benoit
  • 76,634
  • 23
  • 210
  • 236
  • 22
    and I believe ADL in this context just means "argument dependent lookup". That allows the code to use "swap" with or without a local swap function being defined. If a local one doesn't exist, then std::swap is used – vmpstr Jan 24 '11 at 13:49
  • 3
    @vmpstr: If you put that as a separate answer you get 10 reputation just because I vote it up. – Benoit Jan 24 '11 at 13:51
  • 6
    This is a useless answer to be honest. It does not explain the interaction of `using std::swap` and ADL. MSalters' answer should be the one accepted. – Maxim Egorushkin Jan 24 '11 at 14:28
  • 1
    @Maxim Yegorushkin: The answer may be incomplete but if the asker does not know about the `using` keyword then the answer is not useless. FYI I have upvoted MSalters' answer because it is more in-depth than mine. – Benoit Jan 24 '11 at 14:36
  • 1
    @Maxim, my question was mainly about the using keyword, then only asking what ADL is. I'm glad both @Benoit and @MSalters answered 1. and 2. respectively. – Stephane Rolland Jan 25 '11 at 13:32
-1

By adding using std::swap it allows for a wider range of flexibility within that function. There is no type specific version for swap because it is a template, so calling the std versions for any build-in type yields no problems.

Assuming class Foo has a member h that holds type ExampleType and we define a type specific version of swap for ExampleType:

void swap(Foo& lhs, Foo& rhs)
{
    //ERROR: This would only the call std version 
    std::swap(lhs.h, rhs.h);
}

The example above would solely call the std version and not our ExampleType version. So by includingusing std::swap the program will call our defined version and not std::swap:

void swap(Foo& lhs, Foo& rhs)
{
    using std::swap;
    std::swap(lhs.h, rhs.h);   //Using class defined version of swap()
}

Even if we replaced arguments being swapped with build-ins, the code would still execute without errors because the compiler would deduce that the std version would be the best option. This concept is also known as Argument Dependent Lookup or ADL.