concepts lite

51

Upload: platonov-sergey

Post on 15-Apr-2017

1.352 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Concepts lite
Page 2: Concepts lite

От Concepts к Concepts Lite

Александр Фокин Старший разработчик Поиска

Page 3: Concepts lite

План

●  Мотивация

●  Немного истории

●  Concepts Lite

Page 4: Concepts lite

Мотивация

4

Page 5: Concepts lite

Сообщения об ошибках

5

1>include\algorithm(3157):  error  C2784:  'unknown-­‐type  std::operator  -­‐(std::move_iterator<_RanIt>  &,const  std::move_iterator<_RanIt2>  &)'  :    1>                                                                            could  not  deduce  template  argument  for  'std::move_iterator<_RanIt>  &'  from    1>                                                                            'std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>'  1>                    include\xutility(1969)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\algorithm(3164)  :  see  reference  to  function  template  instantiation    1>                                                                        'void  std::sort<_RanIt,std::less<void>>(_RanIt,_RanIt,_Pr)'  being  compiled  1>                    with  1>                    [  1>                            _RanIt=std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>  1>    ,                        _Pr=std::less<void>  1>                    ]  1>                    main.cpp(8)  :  see  reference  to  function  template  instantiation    1>                                                'void  std::sort<std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>>(_RanIt,_RanIt)'  being  compiled  1>                    with  1>                    [  1>                            _RanIt=std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>  1>                    ]  1>                    include\xutility(1969)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(1969)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(1969)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(1969)  :  see  declaration  of  'std::operator  -­‐'  1>include\algorithm(3157):  error  C2784:  'unknown-­‐type  std::operator  -­‐(const  std::reverse_iterator<_RanIt>  &,const  std::reverse_iterator<_RanIt2>  &)'  :    1>                                                                              could  not  deduce  template  argument  for  'const  std::reverse_iterator<_RanIt>  &'    1>                                                                              from  'std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>'  1>                    include\xutility(1130)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(1130)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(1130)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(1130)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(1130)  :  see  declaration  of  'std::operator  -­‐'  1>include\algorithm(3157):  error  C2784:  'unknown-­‐type  std::operator  -­‐(const  std::_Revranit<_RanIt,_Base>  &,const  std::_Revranit<_RanIt2,_Base2>  &)'  :    1>                                                                            could  not  deduce  template  argument  for  'const  std::_Revranit<_RanIt,_Base>  &'    1>                                                                            from  'std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>'  1>                    include\xutility(937)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(937)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(937)  :  see  declaration  of  'std::operator  -­‐'  1>                    include\xutility(937)  :  see  declaration  of  'std::operator  -­‐'  1>                    xutility(937)  :  see  declaration  of  'std::operator  -­‐'  1>include\algorithm(3157):  error  C2676:  binary  '-­‐'  :  'std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>'  does  not  define  this    1>                                                                            operator  or  a  conversion  to  a  type  acceptable  to  the  predefined  operator  1>include\algorithm(3157):  error  C2780:  'void  std::_Sort(_RanIt,_RanIt,_Diff,_Pr)'  :  expects  4  arguments  -­‐  3  provided  1>                    include\algorithm(3121)  :  see  declaration  of  'std::_Sort'  

std::list<int>  list;  std::sort(list.begin(),  list.end());  

Page 6: Concepts lite

Cообщения об ошибках

6

Что видит опытный разработчик Что видит новичок

main.cpp(8):    list<int>::iterator  is  not  a  RandomAccessIterator  

水無月の虚空に涼し時鳥 木をつみて夜の明やすき小窓かな 一重づゝ一重つゝ散れ八重櫻 名月の出るやゆらめく花薄 ちる花にもつるゝ鳥の翼かな 麥蒔やたばねあげたる桑の枝 松杉や枯野の中の不動堂 すゝしさや神と佛の隣同士 御佛に尻むけ居れば月涼し 見下せば月にすゞしや四千軒 月涼し蛙の聲のわきあがる すゞしさや瀧ほとばしる家のあひ 春風に尾をひろげたる孔雀かな 柿くへば鐘が鳴るなり法隆寺 稻の花道灌山の日和かな  

O_O

Page 7: Concepts lite

Перегрузка функций

7

template<class  Iterator,  class  Difference>  typename  std::enable_if<          is_input_iterator<Iterator>  &&  !is_bidirectional_iterator<Iterator>  >::type  advance(Iterator  &i,  Difference  n)  {          while(n-­‐-­‐)  ++i;  }    template<class  Iterator,  class  Difference>  typename  std::enable_if<          is_bidirectional_iterator<Iterator>  &&  !is_random_access_iterator<Iterator>  >::type  advance(Iterator  &i,  Difference  n)  {          if  (n  >  0)  while  (n-­‐-­‐)  ++i;            if  (n  <  0)  while  (n++)  -­‐-­‐i;  }    template<class  Iterator,  class  Difference>  typename  std::enable_if<is_random_access_iterator<Iterator>>::type  advance(Iterator  &i,  Difference  n)  {          i  +=  n;  }  

Page 8: Concepts lite

Перегрузка функций

8

Что видит опытный разработчик Что видит новичок

void  advance(InputIterator  &i,                              Difference  n)    {          while(n-­‐-­‐)  ++i;  }  

template<水無月の虚空に涼し時鳥>  本末転倒  advance(Iterator  &i,                                    Difference  n)  {          while(n-­‐-­‐)  ++i;  }  

O_O

Page 9: Concepts lite

Концепты

9

Динамический полиморфизм: ●  Интерфейсы

Статический полиморфизм: ●  Концепты

interface  List<T>    extends  Collection<T>  {...}    static    <T>  void  sort(List<T>  list);  

template<class  T>    concept  bool  Sortable()  {...}    template<Sortable  Container>  void  sort(Container&  c);  

Java   C++  

Page 10: Concepts lite

Немного истории

10

Page 11: Concepts lite

Концепты в С++

11

1995 2000 2005 2010 2015 2020

1994: STL принята в стандарт С++.

Pre-Standard С++98 С++03 С++11 С++14 С++17+

1996: Благодаря распространению STL шаблоны начинают активно использовать.

2002: Шаблонами из boost пугают детей. Становятся видны проблемы текущей модели шаблонов. Разрабатываются «ограничения на шаблоны» — концепты.

2005: Концепты решено включить в C++0x.

2009: Концепты решено исключить из C++0x.

2013: Concepts Lite — ограничения на шаблоны и ничего больше.

2017: Concepts Lite в C++17

Page 12: Concepts lite

12

Какими были концепты в С++0x?

Page 13: Concepts lite

Проверка аргументов

13 13

template<ForwardIterator  I,  class  V>          requires  Assignable<typename  I::value_type,  V>  void  fill(I  first,  I  last,  const  V&  v);      fill(0,  9,  9.9);                  //  Error:  int  is  not  a  ForwardIterator  fill(&v[0],  &v[9],  9.9);  //  OK  

Page 14: Concepts lite

Проверка реализации

14

template<ForwardIterator  I,  class  V>          requires  Assignable<typename  I::value_type,  V>  void  fill(I  first,  I  last,  const  V  &v)  {          while  (first  !=  last)  {                  *first  =  v;                  first  =  first  +  1;  //  Error:  operator+  not  defined                                                          //                for  ForwardIterator          }  }  

Page 15: Concepts lite

Проверка реализации

15

concept  Storable<class  T>  {            void  store_value(T);    };    template<Storable  T>  void  store(const  T&  value)  {          store_value(value);              //  OK  }            

Page 16: Concepts lite

Проверка реализации

16

concept  Storable<class  T>  {            void  store_value(T);    };    template<Storable  T>  void  store(const  T&  value)  {          store_value(value);              //  OK    #ifdef  _DEBUG          std::cerr  <<  “STORE  ”  <<                    value  <<  std::endl;  #endif  }  

Page 17: Concepts lite

Проверка реализации

17

concept  Storable<class  T>  {            void  store_value(T);    };    template<Storable  T>  void  store(const  T&  value)  {          store_value(value);              //  OK    #ifdef  _DEBUG          std::cerr  <<  “STORE  ”  <<                    value  <<  std::endl;      //  Error:  operator<<  not  defined    #endif                                                //                for  Storable  }  

Page 18: Concepts lite

Расширяемость через concept_map

18

concept  RandomAccessIterator<class  T>  {  /*  ...  */  };              template<RandomAccessIterator  I>  typename  I::value_type  range_max(I  first,  I  last);      int  array[N]  =  {  /*  ...  */  };  std::cout  <<            range_max(&array[0],  &array[N]);  //  Error:  int*  has                                                                              //  no  nested  value_type  

Page 19: Concepts lite

Расширяемость через concept_map

19

concept  RandomAccessIterator<class  T>  {  /*  ...  */  };    template<class  T>  concept_map  RandomAccessIterator<T  *>  {            typedef  T  value_type;  };    template<RandomAccessIterator  I>  typename  I::value_type  range_max(I  first,  I  last);      int  array[N]  =  {  /*  ...  */  };  std::cout  <<            range_max(&array[0],  &array[N]);  //  OK    

Page 20: Concepts lite

Аксиомы

20

concept  TotalOrdering<class  Op,  class  T>  {            bool  operator()(Op,  T,  T);                      axiom  Antisymmetry(Op  op,  T  x,  T  y)  {                    if  (op(x,  y)  &&  op(y,  x))                            x  <=>  y;            }              axiom  Transitivity(Op  op,  T  x,  T  y,  T  z)  {                    if  (op(x,  y)  &&  op(y,  z))                            op(x,  z);            }              axiom  Totality(Op  op,  T  x,  T  y)  {                    op(x,  y)  ||  op(y,  x);            }    }  

Page 21: Concepts lite

Проблемы

21

●  «Слишком много всего»

●  Большое количество спорных моментов

●  Очень много стандартных концептов

Page 22: Concepts lite

Concepts Lite

22

Page 23: Concepts lite

Concepts Lite

23

●  Проверка аргументов в местах вызова

●  Проверка реализации

●  Расширяемость через concept_map

●  Аксиомы для определения семантики

Page 24: Concepts lite

Ограничения на шаблоны

●  Поддержка обобщенного программирования

●  Первый шаг на пути к полноценным концептам

Page 25: Concepts lite

Синтаксис

25

template<Sortable  C>  void  sort(C&  container);  

error:  no  matching  function  call  to  ‘sort(list<int>&)’  note:  candidate  is  ‘sort(C&  container)’  note:      where  C  =  list<int>  note:  template  constraints  not  satisfied  note:      ‘C’  is  not  a/an  ‘Sortable’  type  

list<int>  l;  sort(l);  

Page 26: Concepts lite

Концепты

26

template<class  T>  concept  bool  Sortable  =            PermutableСontainer<T>  &&  TotallyOrdered<ValueType<T>>;      template<class  T>  concept  bool  Integral()  {          return  std::is_integral<T>();  }  

Обычные constexpr шаблонные переменные или функции!

Page 27: Concepts lite

Ограничения на классы

27

template<Object  T,  Allocator  A>  class  vector;    /*  Equivalently:  */    template<class  T,  class  A>        requires  Object<T>  &&  Allocator<A>  class  vector;  

Page 28: Concepts lite

Ограничения на несколько типов

28

template<Sequence  S,  Equality_comparable<Value_type<S>>  T>  Iterator_type<S>  find(S&&  sequence,  const  T&  value);    /*  Equivalently:  */    template<class  S,  class  T>          requires  Sequence<S>  &&  Equality_comparable<T,  Value_type<S>>  Iterator_type<S>  find(S&&  sequence,  const  T&  value);    /*  Or:  */    template<Sequence  S,  class  T>          requires  Equality_comparable<T,  Value_type<S>>  Iterator_type<S>  find(S&&  sequence,  const  T&  value);    

Page 29: Concepts lite

Ограничения на методы

29

template<Object  T,  Allocator  A>  class  vector  {  public:          requires  Copyable<T>          vector(const  vector&  x);                    requires  Movable<T>          void  push_back(T&&  x);  };  

Page 30: Concepts lite

Перегрузка функций

30

template<InputIterator  I>  void  advance(I&  i,  DifferenceType<I>  n)  {          while  (n-­‐-­‐)  ++i;  }    template<BidirectionalIterator  I>  void  advance(I&  i,  DifferenceType<I>  n)  {          if  (n  >  0)  while  (n-­‐-­‐)  ++i;          if  (n  <  0)  while  (n++)  -­‐-­‐i;  }    template<RandomAccessIterator  I>  void  advance(I&  i,  DifferenceType<I>  n)  {          i  +=  n;  }  

Page 31: Concepts lite

Перегрузка функций

31

istream_iterator<int>  iter(cin);  advance(iter,  1);      //  Input  overload    vector<int>::iterator  first  =  v.begin();  advance(first,  1);    //  Random  access  overload  

Компилятор выбирает наиболее «специализированную» перегрузку путем сравнения множеств ограничений на типы.

Page 32: Concepts lite

Специализация шаблонов

32

template<class  T>  struct  numeric_traits;    template<Integral  T>  struct  numeric_traits<T>  :  integral_traits<T>  {  /*...*/  };    template<FloatingPoint  T>  struct  numeric_traits<T>  :  floating_point_traits<T>  {  /*...*/  };  

Page 33: Concepts lite

Обобщенные лямбда-функции

33

vector<string>  v  =  {  /*...*/  };  find_if(v,  [](const  auto&  x)  {  return  x  ==  "hello";  });  

template<class  T>  concept  bool  String  =  /*...*/;  

[](const  String&  x)  {  return  x  ==  "hello";  }    []<String  T>(const  T&  x)  {  return  x  ==  "hello";  }    []  String{T}  (const  T&  x)  {  return  x  ==  "hello";  }  

Page 34: Concepts lite

Обобщенные лямбда-функции

34

template<class  I,  class  P>  concept  bool  Input_query()  =          Input_iterator<I>  &&  Predicate<P,  Value_type<I>>;  

template<class  I,  class  P>          requires  Input_query<I,  P>  I  find_if(I  first,  I  last,  P  pred);    /*  As  a  lambda:  */    auto  find_if  =  []  Input_query{I,  P}  (I  first,  I  last,  P  pred)  {};    /*  As  a  function  with  {}  syntax:  */    Input_query{I,  P}  I  find_if(I  first,  I  last,  P  pred);  

Page 35: Concepts lite

Замена auto

35

Integer  gcd(Integer  a,  Integer  b)  {  /*  ...  */  }    /*  Equivalently:  */    template<Integer  T>    T  gcd(T  a,  T  b);  

Real  y  =  f(x);    /*  Equivalently:  */    auto  y  =  f(x);    static_assert(Real<decltype(y)>(),  "");  

Page 36: Concepts lite

Выражение requires

36

template<class  T>  concept  bool  Equality_comparable  =          requires  (T  a,  T  b)  {                  {a  ==  b}  -­‐>  bool;                  {a  !=  b}  -­‐>  bool;          };      template<class  I>  concept  bool  Readable  =          requires  (I  i)  {                  typename  Value_type<I>;                  {*i}  -­‐>  const  Value_type<I>&;          };  

Page 37: Concepts lite

Концепты

37

●  Возвращают bool

●  Не имеют параметров

●  Не имеют ограничений

●  Объявление должно быть определением

●  Определение не должно быть рекурсивным

●  Перегрузки разрешены только по количеству параметров

Page 38: Concepts lite

Декомпозиция концептов

38

template<class  T>          requires  Equality_comparable<T>  bool  distinct(T  a,  T  b)  {  return  a  !=  b;  }    /*  Decomposed:  */    template<class  T>          requires            __is_valid_expr(declval<T>()  ==  declval<T>())  &&          __is_convertible_to(decltype(declval<T>()  ==  declval<T>()),  bool)  &&          __is_valid_expr(declval<T>()  !=  declval<T>())  &&            __is_convertible_to(decltype(declval<T>()  !=  declval<T>()),  bool)  bool  distinct(T  a,  T  b)  

Page 39: Concepts lite

Декомпозиция концептов

39

Атомарные ограничения

template<class  T>          requires  Equality_comparable<T>  bool  distinct(T  a,  T  b)  {  return  a  !=  b;  }    /*  Decomposed:  */    template<class  T>          requires            __is_valid_expr(declval<T>()  ==  declval<T>())  &&          __is_convertible_to(decltype(declval<T>()  ==  declval<T>()),  bool)  &&          __is_valid_expr(declval<T>()  !=  declval<T>())  &&            __is_convertible_to(decltype(declval<T>()  !=  declval<T>()),  bool)  bool  distinct(T  a,  T  b)  

Page 40: Concepts lite

Атомарные ограничения

40

Все, что не является выражением с операторами && и ||:

●  is_integral<T>::value  

●  !is_void<T>::value  

●  __is_valid_expr(declval<T>()  ==  declval<T>())

Вызовы концептов не являются атомарными.

Page 41: Concepts lite

Упорядочивание концептов

41

template<class  T>  concept  bool  Totally_ordered  =          Weakly_ordered<T>  &&  Equality_comparable<T>;  

Totally_ordered  

Equality_comparable  

Page 42: Concepts lite

Когда?

42

●  В июле 2015 Concepts Lite TS было одобрено комитетом по стандартизации

●  С большой вероятностью будет включено в стандарт C++17

Page 43: Concepts lite

Хотите узнать больше?

43

●  N3701 на https://isocpp.org

●  Лекции Andrew Sutton, одного из авторов предложения по включению Concepts Lite в стандарт

●  Бранч GCC: http://concepts.axiomatics.org/~ans/

●  Реализация части STL c концептами: https://github.com/asutton/origin

Page 44: Concepts lite

Спасибо!

44

Page 45: Concepts lite

Контакты

[email protected]

+7 915 3705385

retgone

retgone

Александр Фокин

Старший разработчик Поиска

Page 46: Concepts lite
Page 47: Concepts lite

47

Addendum

Page 48: Concepts lite

Причины

std::vector<int&>  v;  

Page 49: Concepts lite

Причины

49

1>include\xmemory0(516):  error  C2528:  'pointer'  :  pointer  to  reference  is  illegal  1>                    include\type_traits(572)  :  see  reference  to  class  template  instantiation  'std::allocator<_Ty>'  being  compiled  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>                    include\vector(650)  :  see  reference  to  class  template  instantiation  'std::is_empty<_Alloc>'  being  compiled  1>                    with  1>                    [  1>                            _Alloc=std::allocator<int  &>  1>                    ]  1>                    main.cpp(6)  :  see  reference  to  class  template  instantiation  'std::vector<int  &,std::allocator<_Ty>>'  being  compiled  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>include\xmemory0(517):  error  C2528:  'const_pointer'  :  pointer  to  reference  is  illegal  1>include\xmemory0(548):  error  C2535:  'int  &(*std::allocator<_Ty>::address(int  &)  throw()  const)'  :  member  function  already  defined  or  declared  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>                    include\xmemory0(542)  :  see  declaration  of  'std::allocator<_Ty>::address'  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>include\xmemory0(586):  error  C2528:  '_Ptr'  :  pointer  to  reference  is  illegal  1>include\xmemory0(591):  error  C2528:  '_Ptr'  :  pointer  to  reference  is  illegal  1>include\xmemory0(683):  error  C2528:  'pointer'  :  pointer  to  reference  is  illegal  1>                    include\xmemory0(755)  :  see  reference  to  class  template  instantiation  'std::allocator_traits<_Alloc>'  being  compiled  1>                    with  1>                    [  1>                            _Alloc=std::allocator<int  &>  1>                    ]  1>                    include\vector(443)  :  see  reference  to  class  template  instantiation  'std::_Wrap_alloc<std::allocator<_Ty>>'  being  compiled  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>                    include\vector(579)  :  see  reference  to  class  template  instantiation  'std::_Vec_base_types<_Ty,_Alloc>'  being  compiled  1>                    with  1>                    [  1>                            _Ty=int  &  1>    ,                        _Alloc=std::allocator<int  &>  1>                    ]  1>                    include\vector(652)  :  see  reference  to  class  template  instantiation  'std::_Vector_alloc<false,std::_Vec_base_types<_Ty,_Alloc>>'  being  compiled  1>                    with  1>                    [  1>                            _Ty=int  &  1>    ,                        _Alloc=std::allocator<int  &>  1>                    ]  1>include\xmemory0(684):  error  C2528:  'const_pointer'  :  pointer  to  reference  is  illegal  1>include\xmemory0(795):  error  C2535:  'int  &(*std::_Wrap_alloc<std::allocator<_Ty>>::address(int  &)  const)'  :  member  function  already  defined  or  declared  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>                    include\xmemory0(789)  :  see  declaration  of  'std::_Wrap_alloc<std::allocator<_Ty>>::address'  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>include\xmemory0(861):  error  C2528:  '_Ptr'  :  pointer  to  reference  is  illegal  1>include\xmemory0(105):  error  C2528:  'abstract  declarator'  :  pointer  to  reference  is  illegal  1>                    include\vector(449)  :  see  reference  to  class  template  instantiation  'std::_Is_simple_alloc<std::_Wrap_alloc<std::allocator<_Ty>>>'  being  compiled  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>include\xmemory0(107):  error  C2528:  'abstract  declarator'  :  pointer  to  reference  is  illegal  1>include\xmemory0(122):  error  C2528:  'pointer'  :  pointer  to  reference  is  illegal  1>                    include\vector(469)  :  see  reference  to  class  template  instantiation  'std::_Simple_types<int  &>'  being  compiled  1>                    include\vector(580)  :  see  reference  to  class  template  instantiation  'std::_Vector_val<std::_Simple_types<int  &>>'  being  compiled  1>include\xmemory0(123):  error  C2528:  'const_pointer'  :  pointer  to  reference  is  illegal  1>include\vector(797):  error  C2528:  '_Pval'  :  pointer  to  reference  is  illegal  1>include\vector(1243):  error  C2535:  'void  std::vector<int  &,std::allocator<_Ty>>::push_back(int  &)'  :  member  function  already  defined  or  declared  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>                    include\vector(864)  :  see  declaration  of  'std::vector<int  &,std::allocator<_Ty>>::push_back'  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>include\vector(1327):  error  C2535:  'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int  &>>>  std::vector<int  &,std::allocator<_Ty>>::insert(std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<int  &>>>,_Ty)'  :  member  function  already  defined  or  declared  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>                    include\vector(887)  :  see  declaration  of  'std::vector<int  &,std::allocator<_Ty>>::insert'  1>                    with  1>                    [  1>                            _Ty=int  &  1>                    ]  1>include\vector(1581):  error  C2528:  '_Ptr'  :  pointer  to  reference  is  illegal  1>include\vector(1745):  error  C2528:  '_Pval'  :  pointer  to  reference  is  illegal  

Page 50: Concepts lite

Шаблоны в С++

Методология программирования, основанная на разделении структур данных и алгоритмов через использование абстрактных описаний требований.

Page 51: Concepts lite

Перегруженные функции

51

vector<double>  v{  /*  ...  */  };  Number  n  =  accumulate(v.begin(),  v.end(),  operator*);    /*  Equivalently:  */    Number  n  =  accumulate(          v.begin(),            v.end(),            [](auto  a,  auto  b)  {  return  operator*(a,  b)}  );