Из свеженького:
template< template<class> class Container_Adaptor > struct to_container_consumer_t : public consumer_tag { template< typename Container, typename Item > void consume( Container & to, Item && item ) { Container_Adaptor<Container>::store( to, std::move(item) ); } }; |
Это шаблонный класс, который параметризуется другим шаблонным классом. И у которого всего один шаблонный метод, который параметризуется еще двумя типами.
Задача объекта этого шаблонного класса -- взять некое значение (не суть важно какое) и переместить его в некий контейнер (не суть важно какой). Как именно будет происходить перемещение to_container_consumer_t не знает. Он лишь знает, что это перемещение можно сделать посредством шаблонного параметра Container_Adaptor.
Насколько я понимаю (а понимаю не так, чтобы уж много), to_container_consumer_t -- это метафункция, которая параметризуется другой метафункцией. И в C++ это вот выражается вот таким вот образом.
Так вот, C++ не нужен в мейнстриме именно потому, что в нем можно выражать метафункции, параметризуемые другими метафункциями. А в мейнтриме это никому не нужно. Мягко говоря.
И C++ никуда не денется именно потому, что в нем можно выражать метафункции, параметризуемые другими метафункциями. Это в принципе мало кому нужно. Но, в принципе, нужно. И вот те, кому нужно, и будут продолжать использовать C++.
За последние 3-4 недели довелось поучаствовать в нескольких спорах на тему применимости C++ и востребованности/оправданности новых возможностей C++. И прочитать еще несколько таких споров. И вот что я думаю: C++ должен превратиться во что-то типа Хаскелля. Многие слышали о нем. Многие думают, что это круто и с его помощью можно творить разные крутые вещи. Многие считают, что это не язык для простых смертных. Но мало кто имеет реальное представление о нем. Еще меньше имеют возможность его применять. И еще меньше им владеют.
И, вообще-то говоря, превращение C++ во что-то типа Хаскелля с постепенным отходом от мейнстрима, пойдет на пользу всем. И C++. И тем, кто из него уйдет. И тем, кто в нем останется.
Так думаю на данный момент.
Под катом маленький пример того, как этот to_container_consumer_t используется. И несколько реализаций Container_Adaptor.
template< template<class> class Container_Adaptor = default_container_adaptor > [[nodiscard]] auto to_container() { return impl::to_container_consumer_t<Container_Adaptor>(); } ... [[nodiscard]] auto try_parse( source_t & from ) { std::pair< bool, Container > result; result.first = sequence( repeat( 0, N, symbol(','), ows() ), m_element >> to_container(), repeat( 0, N, ows(), symbol(','), maybe( ows(), m_element >> to_container() ) ) ).try_process( from, result.second ); return result; } |
А вот реализации Container_Adaptor для разных случаев:
template< typename T > struct default_container_adaptor; template< typename T, typename... Args > struct default_container_adaptor< std::vector< T, Args... > > { using container_type = std::vector< T, Args... >; using value_type = typename container_type::value_type; static void store( container_type & to, value_type && what ) { to.push_back( std::move(what) ); } }; template< typename Char, typename... Args > struct default_container_adaptor< std::basic_string< Char, Args... > > { using container_type = std::basic_string< Char, Args... >; using value_type = Char; static void store( container_type & to, value_type && what ) { to.push_back( what ); } }; template< typename K, typename V, typename... Args > struct default_container_adaptor< std::map< K, V, Args... > > { using container_type = std::map< K, V, Args... >; // NOTE: we can't use container_type::value_type here // because value_type for std::map is std::pair<const K, V>, // not just std::pair<K, V>, using value_type = std::pair<K, V>; static void store( container_type & to, value_type && what ) { to.emplace( std::move(what) ); } }; template<> struct default_container_adaptor< nothing_t > { using container_type = nothing_t; using value_type = nothing_t; static void store( container_type &, value_type && ) noexcept {} }; |
6 комментариев:
На мой взгляд программисты делятся на две группы: те, кому нужен Go, и те, кому нужен Хаскель. И тем, и другим в С++ некомфортно.
@Stanislav Mischenko
Не понятно куда потерялись пользователи Fortran-а и Java. Ведь ни те, ни другие особо ни мечтают ни про Go, ни про Haskell.
Поясню. Я просто выбрал эти два языка программирования, как две стороны, в которую клонит программистов. Есть люди, для которых важно сделать, образно выражаясь, А, B, C и получить результат, им будут неинтересны ваши посты на вроде "Шла третья неделя упарывания шаблонами". А есть люди, для которых важно, не столько что делает программа, а то, чтобы было "красиво". Надеюсь теперь понятно. Я не в коем разе не считаю одних лучше других, и в первой, и во второй категории есть адекватные люди. Но я сомневаюсь, что Линус Торвальдс зачитывается Диекстрой.
@Stanislav Mischenko
> А есть люди, для которых важно, не столько что делает программа, а то, чтобы было "красиво".
Мне непонятно это "красиво". И я не стремлюсь сделать красиво, я пытаюсь сделать так, чтобы решение конкретной задачи было более компактно, надежно и проще в сопровождении, чем простое и тривиальное решение "в лоб".
Это здесь пример Higher-Kinded Type. За отсутствие которых любители хаскеля и других продвинутых ЯП ругали Раст.
Про переход С++ из класса рабочих и крестьян в класс заумной экзотики мысль интересная. История покажет...
@Dmitry Popov:
> История покажет...
Если послушать, чего люди пишут в Интернетах, так C++ продолжают использовать либо там, где он уже есть и это традиция (скажем, в легаси или в тяжелых играх, или в профессиональном софте для десктопа), либо там, где команда не боится использовать modern C++ по полной программе и этой команде не приходится думать о том, что написанный ими код придется отдавать на сопровождение индусам, только-только окончившим 3-х месячные курсы "войти-в-ИТ".
Отправить комментарий