Does C++11 change the behavior of explicitly calling std::swap to ensure ADL-located swap's are found, like boost::swap?

后端 未结 4 1723
孤街浪徒
孤街浪徒 2020-12-01 10:32

Background

Consider for this question the following code:

#include 

namespace ns
{
    struct foo
    {
        foo() : i(0) {}
              


        
4条回答
  •  感动是毒
    2020-12-01 11:05

    In C++20, this is finally standardized:

    std::swap(a, b);
    

    This uses ADL to call the correct overload and imposes the correct requirements to use in SFINAE. The magic is specified in [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.174 [ Note: This permits a (qualified or unqualified) call to the customization point to invoke the most appropriate overload for the given arguments. — end note ]

    174) Any library customization point must be prepared to work adequately with any user-defined overload that meets the minimum requirements of this document. Therefore an implementation may elect, under the as-if rule ([intro.execution]), to provide any customization point in the form of an instantiated function object ([function.objects]) even though the customization point's specification is in the form of a function template. The template parameters of each such function object and the function parameters and return type of the object's operator() must match those of the corresponding customization point's specification.

    (emphasis mine)

    And swap is designated as a customization point in [utility.swap]:

    template
      constexpr void swap(T& a, T& b) noexcept(see below);
    

    Remarks: This function is a designated customization point ([namespace.std]) and shall not participate in overload resolution unless is_­move_­constructible_­v is true and is_­move_­assignable_­v is true. The expression inside noexcept is equivalent to:

    is_nothrow_move_constructible_v && is_nothrow_move_assignable_v
    

    Requires: Type T shall be Cpp17MoveConstructible (Table 26) and Cpp17MoveAssignable (Table 28).

    Effects: Exchanges values stored in two locations.

    (emphasis mine)

提交回复
热议问题