Хорошо, когда C++ со временем впитывает в себя хорошие штуки из других языков программирования. Вот тот же if constexpr из C++17 явно позаимствован из D. Жаль только, что static if в D может применяться в большем количестве контекстов, чем if constexpr в C++.
Был бы в C++17 if constexpr таким же мощным, как static if в D, я бы мог написать вот такой вот код сходу, не сильно задумываясь:
template< typename Msg, message_mutability_t Mutability, message_ownership_t Ownership > class message_holder_impl_t final { public : using payload_type = typename message_payload_type< Msg >::payload_type; using envelope_type = typename message_payload_type< Msg >::envelope_type; message_holder_impl_t() noexcept = default; message_holder_impl_t( intrusive_ptr_t< envelope_type > mf ) noexcept : m_msg{ std::move(mf) } {} if constexpr(message_ownership_t::unique == Ownership ) { message_holder_impl_t( const message_holder_impl_t & ) = delete; message_holder_impl_t( message_holder_impl_t && ) noexcept = default; message_holder_impl_t & operator=( const message_holder_impl_t & ) = delete; message_holder_impl_t & operator=( message_holder_impl_t && ) noexcept = default; } friend void swap( message_holder_impl_t & a, message_holder_impl_t & b ) noexcept { using std::swap; swap( a.m_msg, b.m_msg ); } //! Access to the message. const payload_type * get() const noexcept { return get_const_ptr( m_msg ); } //! Access to the message. const payload_type & operator * () const noexcept { return *get(); } //! Access to the message via pointer. const payload_type * operator->() const noexcept { return get(); } if constexpr(message_mutability_t::mutable_message == Mutability) { //! Access to the message. payload_type * get() noexcept { return get_non_const_ptr( m_msg ); } payload_type & operator * () noexcept { return *get(); } payload_type * operator->() noexcept { return get(); } } if constexpr(message_ownership_t::shared == Ownership) { //! Create a smart pointer for the message envelope. intrusive_ptr_t< envelope_type > make_reference() const noexcept { return m_msg; } } else if constexpr(message_ownership_t::unique == Ownership) { //! Create a smart pointer for the message envelope. intrusive_ptr_t< envelope_type > make_reference() noexcept { return { std::move(m_msg) }; } } private : //! Actual message. intrusive_ptr_t< envelope_type > m_msg; }; |
Т.е. состав шаблонного класса и логика поведения отдельных его методов могла бы определяться посредством простых if-ов. Должен message_holder реализовать идиому уникального хранения? Нет проблем, будут у него только конструктор и оператор перемещения, без конструктора/оператора копирования. Хранит message_holder мутабельное сообщение? Не вопрос, просто добавляем неконстантный доступ к содержимому message_holder-а.
Но, к сожалению, такого счастья нам еще не подвезли. Придется теперь ломать голову о том, как достичь этого же эффекта посредством наследования и миксинов...
А в D что, static if и за условную компиляцию отвечает?! Удобно. Впрочем, Уолтер всегда был ненормальным...;)
ОтветитьУдалитьА я вот не согласная с таким static if, да - код писать удобно, но вот читаемость кода снижается на мой взгляд, без бутылки с такими классами не разберешься... В С++ код читать легко, все выверенно, все взвешенно, не зря бухают эти комитеты по стандартизации...
ОтветитьУдалить@Сергей Скороходов
ОтветитьУдалитьФормально за условную компиляцию в D отвечает конструкция version. Но к ней в довесок идут static if и static foreach. И в результате получается инструмент страшной силы :)