4

Here I write a code snippet to see which swap would be called, but the result is neither. Nothing is outputted.

#include<iostream>
class Test {};
void swap(const Test&lhs,const Test&rhs)
{
    std::cout << "1";
}

namespace std
{
    template<>
    void swap(const Test&lhs, const Test&rhs)
    {
        std::cout << "2";
    }
    /* If I remove the const specifier,then this will be called,but still not the one in global namespace,why?
    template<>
    void swap(Test&lhs, Test&rhs)
    {
        std::cout << "2";
    }
    */
}
using namespace std;

int main() 
{
    Test a, b;
    swap(a, b);//Nothing outputed
    return 0;
}  

Which swap is called? And in another circumstance, why is the specialized swap without const specifier called, not the ::swap?

VLL
  • 9,634
  • 1
  • 29
  • 54
choxsword
  • 3,187
  • 18
  • 44
  • What do you mean by "Which swap is called on earth?" – babu646 Apr 04 '18 at 08:26
  • @Bigiansen Because nothing is outputed. – choxsword Apr 04 '18 at 08:27
  • @Ron The **Effective C++** by scott says it's ok to name `std` and provide your own specializaion.And I use `using namespace std` here to test what will happen. – choxsword Apr 04 '18 at 08:27
  • @bigxiao At some level down the line, yes. Just not currently. – Ron Apr 04 '18 at 08:28
  • @bigxiao That means you need to say `using std::swap;`. – juanchopanza Apr 04 '18 at 08:28
  • 1
    This code does not even compile because there is no `std::swap` template declaration available and function signatures do not match `std::swap`. [If you fix it then it would print 1](https://wandbox.org/permlink/hBokJSRlVj2fkEFQ). – user7860670 Apr 04 '18 at 08:30
  • 2
    @Ron It's perfectly fine to add your own specialisations of `std`-defined functions. – Angew is no longer proud of SO Apr 04 '18 at 08:30
  • @VTT I compiled it on VS2015,there's no warning. – choxsword Apr 04 '18 at 08:31
  • @Angew I agree. I just feel currently it introduces more confusion for the OP than it does good. – Ron Apr 04 '18 at 08:32
  • 3
    @Ron No, it does not. They are actually trying to specialise `std::swap`, so they have no other option, really. – Angew is no longer proud of SO Apr 04 '18 at 08:32
  • @VTT It also compiles with GCC 5. Remember that `` is allowed to include additional headers, and also that not all implementations, especially older ones, reject `std::swap` in the signature itself. –  Apr 04 '18 at 08:36
  • 2
    Side note: What is the intention of swapping? Is it meaningful at all to have const parameters? – Aconcagua Apr 04 '18 at 08:39
  • @Aconcagua Well,it may be not appropriate to name `swap` here,I use it to test what will happen in this condition,not really want to `swap` them. – choxsword Apr 04 '18 at 08:41
  • @VTT So is that because the user-provided is preferred compared with the most specialized one?And why do we need the `utility` header? – choxsword Apr 04 '18 at 08:46
  • @bigxiao It is found using ADL. `utility` is required because it is where `swap` template is declared. – user7860670 Apr 04 '18 at 08:52
  • 1
    @bigxiao It remains an interesting question, *but*: Either a function *shall* modify an object provided, or it won't. Having two overloads, one doing so, the other not, is a strong hint that one of them is badly named... – Aconcagua Apr 04 '18 at 08:52
  • The program can compile with `c++03` standard, but not with `c++11` or afterwards. See https://godbolt.org/g/58JSLJ on compiler explorer. – MaxPlankton Apr 04 '18 at 08:59

1 Answers1

15

std::swap() is something like [ref]

template< class T >
void swap( T& a, T& b );

It is a better match than your

void swap(const Test& lhs, const Test& rhs);

for

swap(a, b);

where a and b are non-const. So std::swap() is called, which outputs nothing.

Note that std::swap() participates in overload resolution because of using namespace std;.

Lingxi
  • 14,579
  • 2
  • 37
  • 93
  • Why is `void swap( T& a, T& b );` a better match?I thought the specialized one is prefered. – choxsword Apr 04 '18 at 08:34
  • 8
    @bigxiao the most specialized one that most closely matches your variables is preferred. The most specialized match for your variables IS the non-const version, because your variables are also non-const. – Zinki Apr 04 '18 at 08:35