1

I have a problem with my function template.

I have 3 different collections and I've got iterators for the collections. Now I have to create an function template 'apply' which will do the following: 1. Pass through all elements of collections and check if predicate is true:

1.1 If predicate return true - then element of collection need to be changed with lambda 'passed'

1.2 if predicate return false = then element of collection need to be changed with lambda 'rejected'

Please give me an example how should I write it.

Thank you soo much for help. Updated code here:

#include <iostream>
#include <vector>
#include <list>
#include <functional>

using namespace std;

template<typename T>
void apply(T collBegin, T collEnd, function<bool(int)> f1, function<int(int)> f2, function<int(int)> f3)
{
    for (T actualPosition = collBegin; actualPosition != collEnd; ++actualPosition) {
        if (f1(*actualPosition)) {
            //the argument matches the predicate function f1
            *actualPosition = f2(*actualPosition);
        }
        else {
            //the argument doesn't match the predicate function f1
            *actualPosition = f3(*actualPosition);
        }
    }
}

int main()
{
    int arr[]{ 1,2,3,4,5,6,7,8,9 };

    auto predicate = [](int arg) -> bool { return arg % 2 == 0; };

    auto passed = [](int arg) -> int { return arg / 2; };

    auto rejected = [](int arg) -> int { return (3 * arg) + 1; };

    apply(arr, arr + std::size(arr), predicate, passed, rejected);

    std::vector<int> vec(arr, arr + std::size(arr));
    apply(vec.begin(), vec.end(), predicate, passed, rejected);

    std::list<int> lis(vec.begin(), vec.end());
    apply(lis.begin(), lis.end(), predicate, passed, rejected);


    for (auto e : lis) std::cout << e << " ";
    std::cout << '\n';
}

This code works. But I want to make change it from int to T. How can I do this ?

7
  • 2
    All questions on stackoverflow.com must include all relevant information in the question itself, as plain text. Suspicious links to external web sites, that can stop working at any time rendering the question meaningless, are not acceptable. Commented May 27, 2018 at 16:23
  • I corrected this. Sorry for that. Commented May 27, 2018 at 16:27
  • 1
    One of your lambdas are not like the others. Yet, you declared their std::function types to be the same. There's your problem. Also, vector iterators are not plain pointers, so attempting to use them as T * is not going to work, either. Commented May 27, 2018 at 16:28
  • 1
    Sooo how the code should be looks like ? Can you write an example ? Commented May 27, 2018 at 16:31
  • 2
    Be careful: there is a std::apply. It might not have happened yet, but you might end up accidentally calling it, or at least being confused when it comes up in error messages. This is why you should not write using namespace std; where it will apply to everything. Commented May 27, 2018 at 17:46

1 Answer 1

1

Sooo how the code should be looks like ? Can you write an example ?

The following compiles and runs, but I am not sure if this is what you wanted:

#include <iostream>
#include <vector>
#include <list>
#include <functional>
#include <algorithm>

template<typename T, typename U>
void apply(T collBegin, T collEnd, std::function<bool(U const &)> f1, std::function<U(U const &)> f2, std::function<U(U const &)> f3)
{
    std::for_each(collBegin, collEnd, [&](auto &el) { el = f1(el) ? f2(el) : f3(el); });
}

int main()
{
    std::function<bool(int const &)> predicate = [](int const &arg) -> bool { return arg % 2 == 0; };
    std::function<int(int const &)> passed = [](int const &arg) -> int { return arg / 2; };
    std::function<int(int const &)> rejected = [](int const &arg) -> int { return (3 * arg) + 1; };

    int arr[]{ 1,2,3,4,5,6,7,8,9 };
    apply(arr, arr + sizeof(arr)/sizeof(int), predicate, passed, rejected);

    std::vector<int> vec(arr, arr + sizeof(arr) / sizeof(int));
    apply(vec.begin(), vec.end(), predicate, passed, rejected);

    std::list<int> lis(vec.begin(), vec.end());
    apply(lis.begin(), lis.end(), predicate, passed, rejected);

    for (auto e : lis) std::cout << e << " ";
    std::cout << '\n';
}

https://ideone.com/A30Dl9

1 2 16 4 4 5 34 1 7 
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you, I've updated the code and it looks great. But I have a question: How from here can I change the int to T type to make my function and whole program like a template function apply ?
@Tomas2929 I have altered template a little and you have to be explicit when passing lambda by making it std::function so the argument types could be deduced.
Thank you - I've tested it and it works. But I have last question: What are the requirements for types passed soo the lambda does work ? Could you explain it, please ?
@Tomas2929 added the logic, but seriously, you are now in trouble if you can't explain how it works to your teacher ;)
Thank you soo much for help. We can close the topic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.