вторник, 2 февраля 2016 г.

[prog.c++14] И еще одна демонстрация возможностей современного C++

На LOR-е в обсуждении одной темы всплыла ссылка на фреймворк для Scala под названием LMS (Lightweight Modular Staging). На стартовой страничке есть коротенький примерчик:

class Vector[T:Numeric:Manifest](val dataRep[Array[T]]) {
  def foreach(f: Rep[T] => Rep[Unit]): Rep[Unit] =
    for (i <- 0 until data.length) f(data(i))
  def sumIf(f: Rep[T] => Rep[Boolean]) = { 
    var n = zero[T]; foreach(x => if (f(x)) n += x); n }
}

Фреймворк LMS позволяет привести показанный выше код к более простому виду. Но суть не в этом.

Глядя на обобщенный Scala-вский код я подумал, что у C++ давно сложилась репутация не очень выразительного языка. Мол для выражения простых вещей требуется слишком много телодвижений.

Тем удивительнее было осознать, что в современном C++ именно этот пример может быть записан вполне себе лаконично и без сложной шаблонной магии. Собственно говоря полный вариант, который можно взять, скомпилировать и проверить, выглядит вот так (проверялось под GCC 5.3.0 в режиме C++14):

#include <iostream>
#include <iterator>
#include <vector>

using namespace std;

templatetypename C, typename F >
auto sum_if( C const & v, F f )
{
   std::decay_t< decltype(*begin(v)) > r{};
   forauto const & x : v )
      if( f(x) ) r += x;
   return r;
}

int main()
{
   vector< double > a = { 1.02.00.0, -2.0, -3.04.01.0 };
   cout << sum_if( a, []( auto x ) { return x > 0; } ) << endl;
}

Код шаблонной функции sum_if ничуть не сложнее Scala-овского варианта. Даже при том, что C++ный может принимать на вход не только vector<T>, но и list, forward_list, deque и даже T[N].

Походу, с каждым годом стенания о недостаточной выразительности C++ все больше и больше переходят в категорию мифов. Что не может не радовать.

Комментариев нет: