4

If I have some class type that manages, for example, a resource, and my class needs to define a swap() function as a part of its interface that works on objects of that type, then I usually do:

struct Foo{};

Foo f1, f2;

void swap(Foo& lhs, Foo& rhs){
    // code to swap member data of lhs and rhs
}

int main(){
    using std::swap;
    Foo f1, f2;
    swap(f1, f2);
}
  • Now, am I overloading std::swap, or specializing it?

  • I have learned that if I want to specialize a function/class template of the standard library, then I should open the namespace std and declare the specialization there. e.g:

namespace std{
    void swap(Foo&, Foo&);
}
  • I remember that when specializing std::hash for my types that I intend to using as the element type to unordered associative containers, like std::unordered_map, I do specialize std::hash this way:
namespace std{ // opening namespace std
    template<>
    class hash<Foo>{
          //...
    };
}

So, is this correct? Should I overload or specialize std::swap?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Itachi Uchiwa
  • 3,044
  • 12
  • 26
  • 5
    I would argue, for swap, you should always declare your swap overload in your own namespace, and let ADL find it. See first answer on https://stackoverflow.com/questions/14402990/should-you-overload-swap-in-the-std-namespace – Dave S Apr 05 '21 at 03:01

1 Answers1

2

The standard doesn't generally allow adding overloads or specializations in namespace std:

[namespace.std]/1 Unless otherwise specified, the behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std.

There's an exception for specializing class templates. Your std::hash<Foo> example falls under that:

[namespace.std]/2 Unless explicitly prohibited, a program may add a template specialization for any standard library class template to namespace std provided that (a) the added declaration depends on at least one program-defined type and (b) the specialization meets the standard library requirements for the original template.

You can overload certain standard library functions outside namespace std, relying on ADL for them to be found:

[namespace.std]/7 Other than in namespace std or in a namespace within namespace std, a program may provide an overload for any library function template designated as a customization point, provided that (a) the overload’s declaration depends on at least one user-defined type and (b) the overload meets the standard library requirements for the customization point. [Note: This permits a (qualified or unqualified) call to the customization point to invoke the most appropriate overload for the given arguments. —end note]

std::swap is in fact a customization point.

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85