std::same_as în C++

Concepte C++20: same_as cere exact același tip, convertible_to cere un tip care se poate converti în altul.

Sintaxă
#include <concepts>
template<class T, class U> concept same_as = ...;
template<class From, class To> concept convertible_to = ...;

Ce face std::same_as

std::same_as<T, U> este varianta concept a lui std::is_same_v: tipurile trebuie să fie identice. std::convertible_to<From, To> cere ca o valoare de tip From să poată fi convertită implicit în To (de exemplu int în double, const char* în std::string).

Sunt folosite des în clauze requires pentru a verifica ce returnează o expresie: { x.size() } -> std::convertible_to<std::size_t>. În această formă, tipul expresiei devine automat primul argument al conceptului.

Parametri

Parametru Descriere
T, U / From, To Tipurile comparate, respectiv sursa și ținta conversiei.

Ce returnează

Un concept: o condiție bool verificată la compilare.

Exemple

Exemplul 1: Valori la compilare

#include <concepts>
#include <print>
#include <string>

int main() {
    std::println("same_as<int, int>: {}", std::same_as<int, int>);
    std::println("same_as<int, long>: {}", std::same_as<int, long>);
    std::println("convertible_to<int, double>: {}", std::convertible_to<int, double>);
    std::println("convertible_to<const char*, std::string>: {}", std::convertible_to<const char*, std::string>);
    std::println("convertible_to<std::string, int>: {}", std::convertible_to<std::string, int>);
}

Rezultat

same_as<int, int>: true
same_as<int, long>: false
convertible_to<int, double>: true
convertible_to<const char*, std::string>: true
convertible_to<std::string, int>: false

Exemplul 2: Un concept propriu construit cu ele

AreNume cere o metodă nume() al cărei rezultat se poate converti în std::string.

#include <concepts>
#include <print>
#include <string>

template <class T>
concept AreNume = requires(const T& t) {
    { t.nume() } -> std::convertible_to<std::string>;
};

struct Client { std::string nume() const { return "Ana Popescu"; } };
struct Firma { const char* nume() const { return "Dex SRL"; } };

void salut(const AreNume auto& x) {
    std::string n = x.nume();
    std::println("Bună ziua, {}!", n);
}

template <class T>
    requires std::same_as<T, int>
void doarInt(T x) { std::println("int: {}", x); }

int main() {
    salut(Client{});
    salut(Firma{});
    doarInt(5);
    // doarInt(5L);   // eroare: long nu este același tip cu int
}

Rezultat

Bună ziua, Ana Popescu!
Bună ziua, Dex SRL!
int: 5

Greșeli frecvente

  • Folosești same_as când voiai „orice se poate transforma în”. same_as<T, double> respinge int și float; pentru asta există convertible_to.

Comenzi înrudite

  • std::integral: Concepte C++20 care restrâng un șablon la tipuri întregi (integral) sau reale (floating_point).
  • std::is_same: Verifică la compilare dacă două tipuri sunt exact același tip.
  • concept: Dă un nume unui set de cerințe pentru tipuri, folosit ca să restrângi ce tipuri acceptă un șablon.
  • requires: Scrie cerințe pentru parametrii unui șablon: ca clauză care restrânge șablonul sau ca expresie care verifică dacă un cod este valid.