8Objasnite nivoe bezbednosti u odnosu na izuzetke i kako noexcept utiče na operacije premeštanja, kontejnere i generisanje koda.
Nivoi bezbednosti u odnosu na izuzetke opisuju šta ostaje važeće ako operacija baci izuzetak. Osnovna garancija znači da su invarijante očuvane i da nema curenja resursa, iako se stanje možda promenilo. Jaka garancija podrazumeva semantiku potvrde ili poništavanja: u slučaju neuspeha, vidljivo stanje ostaje nepromenjeno. Garancija bez izuzetaka znači da operacija nikada ne baca izuzetak. Uobičajene tehnike uključuju RAII (Resource Acquisition Is Initialization), rad nad privremenim objektima, idiom „kopiraj i zameni” (engl. copy-and-swap) i takvo raspoređivanje mutacija da se konačna promena izvrši tek nakon što sav kôd koji može baciti izuzetak uspešno završi. `noexcept` predstavlja ugovor: ako funkcija označena sa `noexcept` baci izuzetak, poziva se `std::terminate`. To takođe utiče na generički kôd i kontejnere: na primer, tokom realokacije `std::vector` može premeštati elemente ako je konstruktor premeštanja `noexcept`; u suprotnom može vršiti kopiranje, često putem `std::move_if_noexcept`, kako bi očuvao garancije pri izuzecima. `noexcept` takođe može pomoći pri generisanju koda ili optimizaciji smanjenjem potrebnih putanja za propagaciju izuzetaka, ali samo kada je obećanje tačno.
std::vector<T> v;
// During reallocation, an implementation may effectively do:
T* dest = allocate(new_cap);
for (T& x : old_storage) {
construct(dest++, std::move_if_noexcept(x));
}
Pokušajte da odgovorite na ovo pitanje sa AI trenerom
9Objasnite `std::expected` ili ekvivalentne tipove ishoda kao alternative izuzecima za operacije koje mogu da ne uspeju.
`std::expected<T, E>` predstavlja ili uspešnu vrednost `T` ili eksplicitnu grešku `E`, čineći neuspeh delom povratnog tipa funkcije umesto oslanjanja na propagaciju izuzetaka. Koristan je za operacije sklone greškama gde su greške očekivane i gde pozivaoci treba lokalno da ih obrade, kao što su parsiranje, validacija, mrežni pozivi, pretrage u skladištu podataka i ponovljive backend operacije. Tip greške treba da nosi strukturirane informacije kao što su kod greške, kategorija, mogućnost ponovnog pokušaja, poruka ili mapiranje na HTTP (Hypertext Transfer Protocol) / RPC (Remote Procedure Call). Tipovi ishoda se komponuju proverom i propagiranjem grešaka, a u API-jima u stilu C++23 mogu koristiti monadske operacije kao što su `and_then`, `transform` i `or_else` za ulančavanje koraka bez duboko ugnježdenih uslova. U poređenju sa izuzecima, oni čine tok kontrole i API ugovore eksplicitnim i odlično funkcionišu preko granica bez izuzetaka ili granica ABI-ja (Application Binary Interface); izuzeci mogu i dalje biti prikladni za retke, nelokalne ili zaista izuzetne neuspehe u zavisnosti od pravila projekta.
enum class Errc { BadRequest, NotFound, Timeout, DbUnavailable };
struct Error {
Errc code;
bool retryable;
std::string message;
};
std::expected<User, Error> load_user(UserId id);
HttpResponse handle(UserId id) {
auto user = load_user(id);
if (!user) {
switch (user.error().code) {
case Errc::BadRequest: return {400, user.error().message};
case Errc::NotFound: return {404, "not found"};
case Errc::Timeout: return {503, "try again"};
case Errc::DbUnavailable: return {503, "service unavailable"};
}
}
return {200, serialize(*user)};
}
Pokušajte da odgovorite na ovo pitanje sa AI trenerom