Лямбда как параметр фунцкии

Тема в разделе "LANGS.C", создана пользователем Rel, 22 сен 2011.

  1. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    пусть есть набор функций:
    Код (Text):
    1. uint32_t AddImpl(uint32_t ArgC, uint32_t* ArgV)
    2. {
    3.     uint32_t res = 0;
    4.     for(uint32_t t = 0; t < ArgC; t++)
    5.     { res += ArgV[t]; }
    6.     return res;
    7. }
    8.  
    9. uint32_t SubImpl(uint32_t ArgC, uint32_t* ArgV)
    10. {
    11.     uint32_t res = 0;
    12.     for(uint32_t t = 0; t < ArgC; t++)
    13.     { res -= ArgV[t]; }
    14.     return res;
    15. }
    16.  
    17. // и так далее
    как видно они различаются только одной маленькой операцией над переданным массивом, поэтом для уменьшения кода хотелось бы сделать единую функцию, которая принимала бы параметром допустим лямбда-выражение и применяла его аналогичным образом к переданному массиву... то есть примерно так:
    Код (Text):
    1. // вместо старого вызова:
    2. AddImpl(ArgC, ArgV);
    3. // использовать такой вызов:
    4. CommonImpl(ArgC, ArgV, [](uint32_t a, uint32_t b) -> uint32_t {return a + b;});
    возможно ли так сделать с использованием лямбда выражений или необходимо писать N-отдельных функций и передавать в функцию указатель на них? и если возможно, то как оформить функцию CommonImpl и ее вызовы правильно?) заранее спасибо!

    ЗЫ забыл сказать, что использовать std::function и средства boost я не могу... в википедии пишут:
    не понимаю, что они имеют ввиду под "шаблонным типом", можете пояснить?
     
  2. 100gold

    100gold New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2010
    Сообщения:
    165
    Вот такой вариант можно
    Код (Text):
    1. template<typename datatype, class callback>
    2. datatype process_data(size_t counter, datatype* data, callback& cb)
    3. {
    4.     datatype result = 0;
    5.     for (size_t i=0; i<counter; ++i)
    6.     {
    7.         cb(result, data[i]);
    8.     }
    9.     return result;
    10. }
    11.  
    12. void testthis()
    13. {
    14.     int values[3] = {1,2,3};
    15.     printf("%i\n",process_data(3, values, [](int& result, int x){
    16.         result -= x;
    17.     }));
    18.     printf("%i\n",process_data(3, values, [](int& result, int x){
    19.         result += x;
    20.     }));
    21. }
     
  3. 100gold

    100gold New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2010
    Сообщения:
    165
    А в конкретном примере можно и вот так
    Код (Text):
    1. void testthis()
    2. {
    3.     int values[3] = {1,2,3};
    4.     int result =0;
    5.     std::for_each(&values[0], &values[3], [&result](int x) {
    6.         result += x;
    7.     });
    8.     printf("%i",result);
    9. }
     
  4. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    да... похоже, что подходит, надо будет только уточнить, не будет ли несколько функций в коде генерироваться для лямбд с одинаковыми прототипами... большое спасибо!
     
  5. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    чего может быть проще?

    int foo_add(int a, int b){
    return a + b;
    }

    int foo_sub(int a, int b){
    return a - b;
    }

    int SubImpl(int ArgC, int* ArgV, int (*lambda)(int, int))
    {
    int res = 0;
    for(int t = 0; t < ArgC; t++)
    { res = lambda(res, ArgV[t]); }
    return res;
    }

    CommonImpl(ArgC, ArgV, &foo_add);

    CommonImpl(ArgC, ArgV, &foo_sub);

    // иногда под функцию лучше тип объявить

    typedef int (*Lambda)(int, int);

    вот и все
     
  6. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Есть std::accumulate

    Мои пять копеек с итераторами.
    Код (Text):
    1. #include <algorithm>
    2. #include <vector>
    3. #include <iostream>
    4. #include <iterator>
    5. #include <numeric>
    6.  
    7. template<typename itType, typename funcType>
    8. typename std::iterator_traits<itType>::value_type for_each2(itType first, itType second, funcType func)
    9. {
    10.     typename std::iterator_traits<itType>::value_type result = 0;
    11.     std::for_each(first, second, [&](decltype(result) a) { func(result, a);});
    12.     return result;
    13. }
    14.  
    15. int main (int argc, char* argv[])
    16. {
    17.     std::vector<float> v;
    18.     v.push_back(5);
    19.     v.push_back(6.5f);
    20.     v.push_back(1.5f); 
    21.     std::cout << for_each2(v.begin(), v.end(), [](float& result, float a) { return result += a; }) << std::endl;
    22.  
    23.     std::cout << std::accumulate(v.begin(), v.end(), 0.0f) << std::endl;
    24. }
     
  7. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    с лямбдой красивее код, не надо создавать тонну функций, которые еще и могут заинлайниться оптимизацией, что мне совершенно не нужно...