I have a flatbuffer. This flatbuffer has a vector<T>
that I want to transform using std::transform
into a std::vector<U>
.
It is possible that T
can contain values that are not valid - because they are a plain integer converted to an enum. In this case, I want to abort the whole transform process.
Currently I throw an exception within the lambda of std::transform
and catch it in the function that calls the transform function.
std::transform(deserialized_level.rooms.cbegin(), deserialized_level.rooms.cend(), constant_level_data.rooms.begin(),
[&out_progress, &deserialized_rooms, &deserialized_level](const std::unique_ptr<room_t>& deserialized_room) {
auto r = room_info{};
r.position = int3(deserialized_room->position->x, deserialized_room->position->y, deserialized_room->position->z);
r.sector_width = (unsigned char)(deserialized_room->sector_count_x);
r.sector_length = (unsigned char)(deserialized_room->sector_count_z);
auto sector_dimension = sector_size::normal;
switch(deserialized_room->square_size) {
case 256:
sector_dimension = sector_size::smallest;
break;
case 512:
sector_dimension = sector_size::smaller;
break;
case 1024:
sector_dimension = sector_size::normal;
break;
case 2048:
sector_dimension = sector_size::large;
break;
case 4096:
sector_dimension = sector_size::very_large;
break;
case 8192:
sector_dimension = sector_size::huge;
break;
case 16384:
sector_dimension = sector_size::gigantic;
break;
default:
throw std::runtime_error("Unknown sector size detected!" + std::to_string(deserialized_room->square_size));
}
//...//
return r;
});
How would I model this with std::expected
? A std::vector<std::expected<T,E>>
seems kinda silly.
If the transformation is to be aborted at the first unexpected value, an exception in the lambda is the right choice. It is the only way to cancel a
std::transform
.What you want as a result is probably
std::expected<std::vector<U>, std::string>
. To do this, you put thestd::transform
call into a function that returns a correspondingstd::expected
.Note that you can still throw other exceptions normally. The
std::expected
here only receivesthrow
's withstd::string
.You can use it like this: