2

Is it common to use something like the following in C++?

template <typename T> function<void(vector<T> &)> filter1 = [ ] (vector<T> &vec){
    int count = 0;
    for (T t : vec){
        if ( t.cost < 500 )
            vec.erase(vec.begin()+count);
        count++;
    }
};

template <typename T> void discount(float p, vector<T> &vec){
    filter1<T>(vec);
    int count = 0;
    for (T t : vec) {
        t.cost = t.cost - t.cost * p;
        vec.erase(vec.begin() + count);
        vec.emplace(vec.begin() + count, t);
        count++;
    }

btw I'm calling it tembda, cause its a mixture of Template and Lambda.

SecretOne
  • 23
  • 3
  • 1
    You could `remove_if` anyway (https://stackoverflow.com/questions/36384571/is-there-a-better-alternative-to-stdremove-if-to-remove-elements-from-a-vector) and why only take vectors? You could be more general than that – doctorlove Jul 09 '18 at 11:01
  • 2
    BTW, your lambda invokes UB. – Jarod42 Jul 09 '18 at 11:01
  • `vec.erase(vec.begin() + count); vec.emplace(vec.begin() + count, t);` did you simply means `for(T& t : vec)` and get rid of those lines. – Jarod42 Jul 09 '18 at 11:03
  • 2
    No that's just horrible c++, plus it is wrong (erase in range-based for is ub. You need to use iterator-based iteration and assign the return value of erase to the iterator). – midor Jul 09 '18 at 11:05
  • @Jarod42 I wanted to but it somehow is not updating the value. – SecretOne Jul 09 '18 at 11:06
  • 2
    Idioms come about because they have a good underlying reason. What's your reason for doing this? – StoryTeller - Unslander Monica Jul 09 '18 at 11:33
  • Here is a [Demo](https://ideone.com/JXJnQf). If you still have an issue, provide problematic code in other question. – Jarod42 Jul 09 '18 at 12:06

2 Answers2

6

Is it common to use something like the following in C++?

No.

Firstly, std::function is a heavyweight abstraction which unnecessarily degrades the performance of your code in this case. Secondly, there's no advantage in using a lambda expression here over a simple template function - you are just going to confuse whoever reads your code.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • It could be an advantage to have a *generic lambda*, though - these are much easier to pass to generic algorithms than specific specializations of template functions. – lisyarus Jul 09 '18 at 13:02
3

Template lambdas will be a part of C++20, but your intent was common enough to include in C++14.

C++14 supports this via auto instead of <typename T>:

auto filter_out_low_prices = [] (auto& vec) {
    auto predicate = [](const auto& t){ return t.cost < 500.00; };
    vec.erase(std::remove_if(std::begin(vec), std::end(vec), predicate),
            std::end(vec));
};

template <class V>
void discount(const float p, V& vec){
    filter_out_low_prices(vec);
    for (auto& t : vec)
        t.cost = t.cost - t.cost * p;
}

This avoids the use of std::function to be lightweight, as Vittorio Romeo suggested. It also uses remove_if to avoid undefined behavior and is not limited to std::vector, as doctorlove suggested.

Taylor Nichols
  • 588
  • 2
  • 13