...думаю я, когда вижу "шедевры" вроде вот такого:
|
bool data_holder::write_to(const destination & to, const format_version & ver) { if(!m_updated) return true; std::unique_ptr<abstract_data_writer> writer{ (ver == version_x_y || ver == version_y_z) ? static_cast<abstract_data_writer *>(new legacy_data_writer{to, ver}) : ( (ver == version_z_q) ? static_cast<abstract_data_writer *>(new modern_data_writer{to}) : throw unsupported_format_version{ver} ) }; writer->write_meta_data(...); writer->write_headers(...); writer->write_comments(...); const bool result = writer->complete(); m_updated = !result; return result; } |
Расшифровывать многоэтажное выражение с вложенными тернарными операторами, как по мне, то еще удовольствие. И главный вопрос, который у меня возникает при взгляде на этот код: а почему было не использовать здесь лямбду в качестве локальной функции?
Например, вот так:
|
bool data_holder::write_to(const destination & to, const format_version & ver) { if(!m_updated) return true; auto writer = [&]() -> std::unique_ptr<abstract_data_writer> { if(ver == version_x_y || ver == version_y_z) return std::make_unique<legacy_data_writer>(to, ver); else if(ver == version_z_q) return std::make_unique<modern_data_writer>(to); throw unsupported_format_version{ver}; }(); writer->write_meta_data(...); writer->write_headers(...); writer->write_comments(...); const bool result = writer->complete(); m_updated = !result; return result; } |
Здесь и вникнуть в суть происходящего проще, да и расширить со временем новым типом writer-а будет проще.
Но, честно говоря, я бы предпочел другой вариант, т.к. не люблю создавать в динамической памяти то, что спокойно может жить на стеке:
|
bool data_holder::write_to(const destination & to, const format_version & ver) { if(!m_updated) return true; const auto do_write = [this](abstract_data_writer & writer) { writer.write_meta_data(...); writer.write_headers(...); writer.write_comments(...); const bool result = writer.complete(); m_updated = !result; return result; }; if(ver == version_x_y || ver == version_y_z) { legacy_data_writer writer{to, ver}; return do_write(writer); } else if(ver == version_z_q) { modern_data_writer writer{to}; return do_write(writer); } throw unsupported_format_version{ver}; } |
Придерживаюсь мнения, что любой из показанных альтернативных вариантов гораздо проще в восприятии и сопровождении, чем оригинал.
PS. Пожалуйста, не спрашивайте почему в оригинальном коде используется static_cast (а он там и не нужен). У меня нет цензурного ответа.
2 комментария:
а как без static_cast? тернарка должна иметь одинаковые типы в обеих частях
Да, вы правы.
Отправить комментарий