14. hét: Concepts

Czirkos Zoltán · 2022.06.21.

Racionális szám

A racionális szám két egész szám hányadosa. Egész számból viszont többféle is van: short, int, long long – eldönthetjük, mennyi memóriát szánunk egy szám tárolására, és ettől függ a legnagyobb ábrázolható szám. Még akár egy saját típust is definiálhatunk. Pl. BigInt<512>, ha sablonparaméterrel szeretnénk megadni a bitek számát. Vagy simán BigInt, ha dinamikusan változhat.

Írj az első előadás törtes feladatához hasonló osztályt, aminek sablonparamétere, milyen típusú változóval tárolja a számlálót és a nevezőt!

Definiáld az osztályhoz és a hozzá tartozó függvényekhez a concept-eket, add meg, mi a feltétele annak, hogy egy típussal a racionális szám osztály példányosítható legyen!

Írj saját egész szám típust, és példányosítsd vele a törtet! Ellenőrizd static_assert-tel, hogy a típusod teljesíti-e az elvárásokat!

Megoldás

Egy lehetésges megoldás (ez a saját típust nem tartalmazza):

#include <type_traits>
#include <iostream>

template <typename T>
concept bool Integral() {
    return std::is_integral<T>::value;
}

template <typename T>
concept bool Serializable() {
    return requires (std::ostream & os, std::istream & is, T obj) {
        { os << obj } -> std::ostream &;
        { is >> obj } -> std::istream &;
    };
}

template <Integral INT>
class Rational {
  public:
    Rational(INT num, INT den) {}
    INT num() const { return num_; }
    INT den() const { return den_; }
  private:
    INT num_;
    INT den_;
};

template <typename INT>
    requires Serializable<INT>()
std::ostream & operator<<(std::ostream &os, Rational<INT> const & r) {
    os << r.num() << '/' << r.den();
    return os;
}

template <typename INT>
    requires Serializable<INT>()
std::istream & operator>>(std::istream &is, Rational<INT> const & r) {
    return is;
}


int main() {
    Rational<int> r(2, 3);
    std::cout << r;
    std::cin >> r;
}