

//strumień jest skonfigurowany w taki sposób, że nie zgłasza wyjątków
//basic_istram& operator>>(int& value);
//wykorzystujemy funkcję, która pomija białe znaki, wczytuje cyfry i dostarcza liczbę całkowitą.

//możemy badać flagi metodami w klasie bazowej
// bool ios::good(); //poprawny stan strumienia
// bool ios::eofbit() const //pusty strumien
// bool ios::failbit() const //blad formatowania, np. litery zamiast cyfr
// bool ios::badbit() const //blad strumienia

//zwraca liczbę całkowitą typu INT, albo jest błąd (napis zawiera cyfry, lub liczba jest za długa)
//
using namespace std;

#include <iostream>
#include <sstream>
#include <exception>
#include <string>
#include <variant>


static const int ERROR_EMPTY = -1;
static const int ERROR_BAD = -2;

int read(istream& is) {
    if(is.peek() == EOF) {
        return ERROR_EMPTY;
    }
    int out = 0;
    is >> out;
    if(is.fail() || is.bad() )
        return ERROR_BAD;
    else
        return out;
}

class Error : public std::exception {
public:
    Error(const string& m) : msg_(m) {}
    const std::string get() const { return msg_; }
    const std::string msg_;
};

//wykorzystuje wariant, prawidłowo jest także użyć std::expected
variant<int,Error> readBetter(istream& is) {
    if(is.peek() == EOF) {
        return Error("Empty string");
    }
    int out = 0;
    is >> out;
    if(is.fail() || is.bad() )
        return Error("Bad string");
    else
        return out;
}

struct VisitReadOutput
{
    void operator()(const int& i) { cout << "read " << i << endl; }
    void operator()(const Error& e) { cout << "error: " << e.get() << endl; }
};

int main() {
    for( const char* s : { "1", "", "a", "111111111111111111111111111111111111" } ) {
        istringstream is(s);
        cout << read(is) << endl;

        istringstream is2(s);
        std::visit(VisitReadOutput(), readBetter(is2) );

    }
    // istringstream is("1");

    // cout << read(is) << endl;
    // istringstream is2("");
    // cout << read(is2) << endl;
    // istringstream is3("aaaaa");
    // cout << read(is3) << endl;

    return 0;
};
