Da li ste zamenili exception-e sa tagovanim unijama?

  • Začetnik teme Začetnik teme bmaxa
  • Datum pokretanja Datum pokretanja

bmaxa

Legenda
Poruka
70.808
Trend je uveliko da se error hendling zameni sa tagovanim unijama, pa ja vec neko vreme
ne koristim exceptione u C++, nego sam napisao klasu koja mimikuje Rustov Result<T,E>.
C++:
#include <string>
namespace MyNamespace {
    template <class T>
    struct Ok {
        T val;
    };
    template <class T>
    struct Err {
        T val;
    };
    template <class V> Ok<V> make_ok(V v) {
        Ok<V> rc;
        rc.val = v;
        return rc;
    }
    template <class V> Err<V> make_err(V v) {
        Err<V> rc;
        rc.val = v;
        return rc;
    }
    template <class O, class E>
    struct Result {
        enum {OK,ERR} tag;
        union {
            O ok;
            E err;
        };
        Result(const Err<E>& err):tag(ERR),err(err.val) {

        }
        Result(const Ok<O>& ok):tag(OK),ok(ok.val) {

        }
        Result(const Result& in) {
            tag = in.tag;
            switch (tag) {
            case OK: *new(&ok)O() = in.ok;
                break;
            case ERR: *new(&err)E() = in.err;
                break;
            }
        }
        Result& operator=(const Result& in) {
            if (this == &in)return *this;
            this->~Result();
            tag = in.tag;
            switch (tag) {
            case OK: *new(&ok)O() = in.ok;
                break;
            case ERR: *new(&err)E() = in.err;
                break;
            }
            return *this;
        }
        ~Result() {
            if (tag == ERR) { err.~E(); }
            else { ok.~O(); }
        }
        bool isOk()const { return tag == OK; }
        bool isErr()const { return tag == ERR; }
        O& Ok() { return ok; }
        E& Err() { return err; }
    };
    typedef Result<int, std::string> result_t;
    extern const result_t rc0;
}

Koristi se vrlo jednostavno, samo treba proveriti sa li je isOk pa dobiti resultat a ko je isErr handlovati gresku.
znaci result_t func();
auto rc = func();
if (rc.isErr()){ cerr<< rc.Err() <<std::endl(); }
i u samoj f-ji make_ok i make_err.
Ovaj trend je poceo sa Rust, a ideja je iz funckionalnog programiranja gde se koristi ovaj nacin (Haskell Either i Maybe tipovi).
I tako. Postoji i predlog od Herb Sutter-a da se C++ exceptioni implementiraju na ovaj nacin.
Pomenuti Zig ima u sam jezik ugradjen ovaj mehanizam koliko autor smatra da je ispravno.
 
Poslednja izmena od moderatora:
Kada bi došao neki početnik i pogledao ovaj kod, pao bi u nesvest. Ljudi imaju problem da razumeju koncept pointera i reference. :mrgreen:
Lepo si napisao, dobro je. Samo, zašto pišeš:
C++:
typedef Result<int, std::string> result_t;
std::string
Što nisi usinig namespace? Je li to zato što ga nisi koristio često ili ti je to praksa oduvek bila?
 
Kada bi došao neki početnik i pogledao ovaj kod, pao bi u nesvest. Ljudi imaju problem da razumeju koncept pointera i reference. :mrgreen:
Lepo si napisao, dobro je. Samo, zašto pišeš:
C++:
typedef Result<int, std::string> result_t;
std::string
Što nisi usinig namespace? Je li to zato što ga nisi koristio često ili ti je to praksa oduvek bila?
To je nova sintaksa, treba da se naviknem :)
 

Back
Top