Ce face requires
Clauza requires se pune după lista de parametri a șablonului (sau după semnătura funcției) și conține o condiție la compilare: requires std::integral<T> && (sizeof(T) >= 4). Dacă tipul nu o îndeplinește, șablonul este ignorat pentru acel tip.
Expresia requires(parametri) { ... } dă true dacă tot codul dintre acolade este valid pentru tipurile date. Codul nu este executat, doar verificat. Poți cere și tipul rezultatului: { x.size() } -> std::convertible_to<std::size_t>;.
Cele două se combină des: requires requires(T x) { ... } (clauză care conține o expresie) sau, mai lizibil, o expresie salvată într-un concept cu nume. Expresia funcționează și într-un if constexpr.
Exemple
Exemplul 1: Clauză requires și supraîncărcare
Pentru tipurile întregi se alege prima variantă, pentru restul a doua. Clauza decide la compilare care funcție se potrivește.
#include <concepts>
#include <print>
template <typename T>
requires std::integral<T>
void descrie(T x) {
std::println("{} este întreg", x);
}
template <typename T>
requires (!std::integral<T>)
void descrie(T x) {
std::println("{} nu este întreg", x);
}
int main() {
descrie(42);
descrie(3.14);
descrie("Iași");
}
Rezultat
42 este întreg
3.14 nu este întreg
Iași nu este întreg
Exemplul 2: Expresie requires în if constexpr
Funcția verifică la compilare dacă tipul are .size(). std::string și std::vector au, int nu.
#include <print>
#include <string>
#include <vector>
template <typename T>
void marime(const T& x) {
if constexpr (requires { x.size(); }) {
std::println("are {} elemente", x.size());
} else {
std::println("nu are size()");
}
}
int main() {
marime(std::string("Brașov"));
marime(std::vector<int>{1, 2, 3});
marime(2025);
}
Rezultat
are 7 elemente
are 3 elemente
nu are size()
Greșeli frecvente
- Scrii
requires !std::integral<T>fără paranteze. Gramatica cere paranteze în jurul expresiilor care nu sunt simple:requires (!std::integral<T>). - Crezi că o expresie
requiresexecută codul. Codul doar este verificat dacă se compilează; nu are efecte.
Comenzi înrudite
concept: Dă un nume unui set de cerințe pentru tipuri, folosit ca să restrângi ce tipuri acceptă un șablon.template: Scrie o funcție sau o clasă o singură dată, pentru orice tip; compilatorul generează varianta potrivită pentru fiecare tip folosit.if constexpr: Un if evaluat la compilare: ramura falsă este eliminată complet, deci poate conține cod care nu s-ar compila pentru tipul curent.