Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What user-defined function signatures are expected to have a specific purpose?

Tags:

c++

The C++ language defines swappable as

Any lvalue or rvalue of this type can be swapped with any lvalue or rvalue of some other type, using unqualified function call swap() in the context where both std::swap and the user-defined swap()s are visible.

also

Many standard library functions (for example, many algorithms) expect their arguments to satisfy Swappable

This means that if I write a function and happen to name it swap( Foobar&, Foobar& ) its existence alone could affect the behavior of calls to the standard library, such as std::sort.

The standard library is expecting my own function to perform a specific task, because of its unqualified signature.

Are there any other user-defined function signatures that are expected by the standard to perform some specific task?

like image 605
Drew Dormann Avatar asked Oct 19 '25 14:10

Drew Dormann


1 Answers

The standard specifies that when the following non-member functions are called, their meanings are "established as-if by performing argument-dependent lookup only". That is, if these function (or function template) names are defined in the same namespace as a program-defined type, they may be called by standard library facilities when that type is involved.

  • swap (the lookup also finds the std::swap overloads)

  • make_error_code (only if is_error_code_enum is specialized)

  • make_error_condition (only if is_error_condition_enum is specialized)

  • submdspan_mapping

  • strong_order (called by std::strong_order)

  • weak_order (called by std::weak_order)

  • partial_order (called by std::partial_order)

  • iter_move (called by std::ranges::iter_move, and indirectly by many ranges facilities)

    • iter_move(e) is required to return a value equal to *e (but possibly with a different type and/or value category).
  • iter_swap (called by std::ranges::iter_swap, and indirectly by many ranges facilities)

    • iter_swap(e1, e2) is required to exchange the values denoted by e1 and e2.
  • begin (called by std::ranges::begin, and indirectly by many ranges facilities; also used by range-based for loop)

    • begin(e) must return an input_or_output_iterator. Otherwise it is not used.
  • end (called by std::ranges::end, and indirectly by many ranges facilities; also used by range-based for loop)

    • end(e) must return a type that satisfies sentinel_for<decltype(ranges::begin(e))>. Otherwise it is not used.
  • rbegin (called by std::ranges::rbegin)

    • rbegin(e) must return an input_or_output_iterator. Otherwise it is not used.
  • rend (called by std::ranges::rend)

    • rend(e) must return a type that satisfies sentinel_for<decltype(ranges::rbegin(e))>. Otherwise it is not used.
  • size (called by std::ranges::size, and indirectly by many ranges facilities)

    • size(e) must return an integer-like type. Otherwise it is not used.

In addition, many member functions and operators may be used by the standard library. For example, std::stack expects a container-like type, and std::istream_iterator expects a type that supports operator >>.

like image 117
cpplearner Avatar answered Oct 21 '25 03:10

cpplearner