std::midpoint(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

✨ std::midpoint(3) ✨

okay so this is a page from the C++ Standard Library manual (C++ Standard Libary, yes that's how the header spells it, we don't fix it, we love her anyway) and bestie, it's literally about the most wholesome little function ever: std::midpoint. it finds the middle. that's it. that's the whole vibe. πŸŽ€


πŸ’– NAME πŸ’–

std::midpoint β€” literally std::midpoint, she contains multitudes, the name is the name 🫢


✨ Synopsis ✨

First things first, she lives in this header:

#include <numeric>

And here's her whole gorgeous signature situation:

template< class T >                        (1) (since C++20)
constexpr T midpoint( T a, T b ) noexcept;
template< class T >                        (2) (since C++20)
constexpr T* midpoint( T* a, T* b );

So what does she do? She computes the midpoint of the integers, floating-points, or pointers a and b. that's the whole job. middle-finding icon behavior πŸ‘‘

  1. This overload only shows up in overload resolution if T is an arithmetic type other than bool. (sorry bool, not today πŸ’€)
  2. This overload only shows up in overload resolution if T is an object type. And heads up: using this overload is ill-formed if T is an incomplete type. so don't do that. πŸ™ˆ

πŸ¦‹ Parameters πŸ¦‹

  • a, b β€” integers, floating-points, or pointer values. the two besties who need a middle friend πŸ’…

🌸 Return value 🌸

  1. Half the sum of a and b. and the best part? No overflow occurs. none. zero. not a single one. πŸŽ‰ If a and b have integer type and the sum is odd, the result is rounded towards a. If a and b have floating-point type, at most one inexact operation occurs. (at most one, she's precise like that ✨)
  2. If a and b point to, respectively, x[i] and x[j] of the same array object x (for the purpose of pointer arithmetic), it returns a pointer to x[i + (j - i) / 2] (or, equivalently x[std::midpoint(i, j)]), where the division rounds towards zero. BUT β€” and this is the important part bestie β€” if a and b do not point to elements of the same array object, the behavior is undefined. 🫠 undefined behavior is not the vibe. don't.

🧚 Exceptions 🧚

Throws no exceptions. literally none. she said "no drama, only midpoint." 😌


πŸ’œ Notes πŸ’œ

Overload (2) can be simply implemented as return a + (b - a) / 2; on common platforms. sounds easy right? but nope β€” such an implementation is not guaranteed to be portable, because there may be some platforms where creating an array with a number of elements greater than PTRDIFF_MAX is possible, and b - a may result in undefined behavior even if both b and a point to elements in the same array. so like, the shortcut is giving "works on my machine" energy and that's not it. 😭

Also there's a feature-test macro, and she's a whole table, iykyk:

  • __cpp_lib_interpolate β€” value 201902L, standard (C++20), feature: std::lerp, std::midpoint 🌈

πŸ”₯ Example πŸ”₯

// Run this code

#include <cstdint>
#include <iostream>
#include <limits>
#include <numeric>

int main()
{
    std::uint32_t a = std::numeric_limits<std::uint32_t>::max();
    std::uint32_t b = std::numeric_limits<std::uint32_t>::max() - 2;

    std::cout << "a: " << a << '\n'
              << "b: " << b << '\n'
              << "Incorrect (overflow and wrapping): " << (a + b) / 2 << '\n'
              << "Correct: " << std::midpoint(a, b) << "\n\n";

    auto on_pointers = [](int i, int j)
    {
        char const* text = "0123456789";
        char const* p = text + i;
        char const* q = text + j;
        std::cout << "std::midpoint('" << *p << "', '" << *q << "'): '"
                  << *std::midpoint(p, q) << "'\n";
    };

    on_pointers(2, 4);
    on_pointers(2, 5);
    on_pointers(5, 2);
    on_pointers(2, 6);
}

🌟 Output 🌟

a: 4294967295
b: 4294967293
Incorrect (overflow and wrapping): 2147483646
Correct: 4294967294

std::midpoint('2', '4'): '3'
std::midpoint('2', '5'): '3'
std::midpoint('5', '2'): '4'
std::midpoint('2', '6'): '4'

like, look at that. the "incorrect" one overflowed and wrapped and gave a whole wrong answer, and std::midpoint just ✨ delivered ✨ the correct one. and the pointer version rounds towards zero so ('5', '2') gives you '4' not '3' β€” she's got rules and she's sticking to them πŸ’… periodt.


πŸ“ References πŸ“

  • C++23 standard (ISO/IEC 14882:2023):
    • 27.10.16 Midpoint [numeric.ops.midpoint]
  • C++20 standard (ISO/IEC 14882:2020):
    • 25.10.15 Midpoint [numeric.ops.midpoint]

(the receipts, in case anyone tries to come for her πŸ‘‘)


🌈 See also 🌈

  • lerp β€” linear interpolation function, (C++20) (function) β€” her cousin who interpolates. different job, same family. 🫢

🌸 anyway bestie that's the whole page, no cap, every detail intact, we ate and left no crumbs πŸ’– this masterpiece was brought to you by http://cppreference.com, dated 2024.06.10, and yeah the footer still says std::midpoint(3) because she's iconic and she knows it ⭐

πŸ“¦ where this page comes from