Namensräume
Varianten
Aktionen

std::ranges::clamp

Von cppreference.com
< cpp‎ | algorithm‎ | ranges
 
 
Algorithmenbibliothek
Beschränkte Algorithmen und Algorithmen für Bereiche (C++20)
Beschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Ausführungsrichtlinien (C++17)
Nicht-modifizierende Sequenzoperationen
Stapeloperationen
(C++17)
Suchoperationen
(C++11)                (C++11)(C++11)

Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Ordnungsändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Zusammenführungsoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikographische Vergleichsoperationen
Permutationsoperationen
C-Bibliothek
Numerische Operationen
Operationen auf uninitialisiertem Speicher
 
Eingeschränkte Algorithmen
Alle Namen in diesem Menü gehören zum Namespace std::ranges
Nicht-modifizierende Sequenzoperationen
Modifizierende Sequenzoperationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen (auf sortierten Bereichen)
       
       
Mengenoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
       
       
clamp

Permutationsoperationen
Faltoperationen
Operationen auf uninitialisiertem Speicher
Rückgabetypen
 
Definiert in Header <algorithm>
Aufruf-Signatur
template< class T, class Proj = std::identity,

          std::indirect_strict_weak_order<std::projected<const T*, Proj>> Comp =
              ranges::less >
constexpr const T&

    clamp( const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {} );
(seit C++20)

Wenn der Wert von v innerhalb von [lohi] liegt, wird v zurückgegeben; andernfalls wird die nächstgelegene Grenze zurückgegeben.

Das Verhalten ist undefiniert, wenn lo größer als hi ist.

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als niebloids bekannt), d.h.

Inhalt

[bearbeiten] Parameter

v - Der Wert, der geklemmt werden soll
lo, hi - die Grenzen, auf die v geklemmt werden soll
comp - Der Vergleich, der auf die projizierten Elemente angewendet werden soll
proj - Die Projektion, die auf v, lo und hi angewendet werden soll

[bearbeiten] Rückgabewert

Referenz auf lo, wenn der projizierte Wert von v kleiner ist als der projizierte Wert von lo, Referenz auf hi, wenn der projizierte Wert von hi kleiner ist als der projizierte Wert von v, andernfalls Referenz auf v.

[bearbeiten] Komplexität

Höchstens zwei Vergleiche und drei Anwendungen der Projektion.

[bearbeiten] Mögliche Implementierung

struct clamp_fn
{
    template<class T, class Proj = std::identity,
             std::indirect_strict_weak_order<std::projected<const T*, Proj>>
                 Comp = std::ranges::less>
    constexpr const T& operator()(const T& v, const T& lo, const T& hi,
                                  Comp comp = {}, Proj proj = {}) const
    {
        auto&& pv = std::invoke(proj, v);
 
        if (std::invoke(comp, std::forward<decltype(pv)>(pv), std::invoke(proj, lo)))
            return lo;
 
        if (std::invoke(comp, std::invoke(proj, hi), std::forward<decltype(pv)>(pv)))
            return hi;
 
        return v;
    }
};
 
inline constexpr clamp_fn clamp;

[bearbeiten] Hinweise

Das Erfassen des Ergebnisses von std::ranges::clamp per Referenz erzeugt eine verwaiste Referenz, wenn einer der Parameter ein temporäres Objekt ist und dieser Parameter zurückgegeben wird.
int n = -1;
const int& r = std::ranges::clamp(n, 0, 255); // r is dangling

Wenn v mit einer der Grenzen als äquivalent verglichen wird, wird eine Referenz auf v zurückgegeben, nicht auf die Grenze.

Diese Funktion sollte nicht mit einer Projektion verwendet werden, die per Wert zurückgibt, und einem Komparator, der Argumente per Wert annimmt, es sei denn, ein Verschieben vom Rückgabetyp des Projektionsergebnisses zum Parametertyp des Komparators ist äquivalent zu einer Kopie. Wenn der Vergleich über std::invoke das Ergebnis der Projektion ändern würde, ist das Verhalten aufgrund der semantischen Anforderungen von std::regular_invocable (enthalten in std::indirect_strict_weak_order) undefiniert.

Der Standard verlangt, dass die Wertkategorie des Ergebnisses der Projektion beibehalten wird, und proj kann nur einmal für v aufgerufen werden, was bedeutet, dass ein Projektionsergebnis, das ein prvalue ist, zwischengespeichert und zweimal verschoben werden muss, um die beiden Aufrufe des Komparators durchzuführen.

  • libstdc++ hält sich nicht daran und übergibt das Projektionsergebnis immer als lvalue.
  • libc++ führte die Projektion zweimal aus, was in Clang 18 behoben wurde.
  • MSVC STL führte die Projektion zweimal aus, was in VS 2022 17.2 behoben wurde.

[bearbeiten] Beispiel

#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>
 
using namespace std::literals;
namespace ranges = std::ranges;
 
int main()
{
    std::cout << "[raw] [" << INT8_MIN << ',' << INT8_MAX << "] "
                 "[0" << ',' << UINT8_MAX << "]\n";
    for (int const v : {-129, -128, -1, 0, 42, 127, 128, 255, 256})
        std::cout << std::setw(4) << v
                  << std::setw(11) << ranges::clamp(v, INT8_MIN, INT8_MAX)
                  << std::setw(8) << ranges::clamp(v, 0, UINT8_MAX) << '\n';
    std::cout << std::string(23, '-') << '\n';
 
    // Projection function
    const auto stoi = [](std::string s) { return std::stoi(s); };
 
    // Same as above, but with strings
    for (std::string const v : {"-129", "-128", "-1", "0", "42",
                                "127", "128", "255", "256"})
        std::cout << std::setw(4) << v
                  << std::setw(11) << ranges::clamp(v, "-128"s, "127"s, {}, stoi)
                  << std::setw(8) << ranges::clamp(v, "0"s, "255"s, {}, stoi)
                  << '\n';
}

Ausgabe

[raw] [-128,127] [0,255]
-129       -128       0
-128       -128       0
  -1         -1       0
   0          0       0
  42         42      42
 127        127     127
 128        127     128
 255        127     255
 256        127     255
-----------------------
-129       -128       0
-128       -128       0
  -1         -1       0
   0          0       0
  42         42      42
 127        127     127
 128        127     128
 255        127     255
 256        127     255

[bearbeiten] Siehe auch

Gibt den kleineren der beiden Werte zurück
(Algorithmus-Funktionsobjekt)[bearbeiten]
Gibt den größeren der beiden Werte zurück
(Algorithmus-Funktionsobjekt)[edit]
(C++20)
prüft, ob ein Ganzzahlwert im Bereich eines gegebenen Ganzzahltyps liegt
(Funktionsvorlage) [edit]
(C++17)
klemmt einen Wert zwischen einem Paar von Grenzwerte
(Funktionsvorlage) [editieren]