1
\$\begingroup\$

This code basically allows you to provide a collection and a lambda and have the lambda operate on each value iterated even allowing modification of the data if you wish.

I would like to be able to reduce the calling of my template advfind to something more concise along the lines of what I could do if I used std::find (i.e. not all of the template parameters).

template<class _coltype, class _valtype>
auto advfind(_coltype& _collection, std::function<bool(_valtype& value)> _fnCompare)
{
    for (_valtype &item : _collection)
    {
        if (_fnCompare(item))
        {
            return true;
        }
    }

    return false;
}

int main()
{
    typedef tuple<int, wstring> MyTuple;
    vector<MyTuple> myints;

    myints.push_back(make_tuple<int, wstring>(1, L"One"));
    myints.push_back(make_tuple<int, wstring>(2, L"Two"));
    myints.push_back(make_tuple<int, wstring>(3, L"Three"));
    myints.push_back(make_tuple<int, wstring>(4, L"Four"));

    // must pass in parameter as a reference type if you wish to modify the collection
    // Can I make this more concise? like advfind(myints, [&](auto &value)
    auto result = advfind<vector<MyTuple>, MyTuple>(myints, [&](auto &value) {
        if (get<0>(value) == 3)
        {
            get<1>(value) = std::wstring(L"I've changed!");
            return true;
        }

        return false;
    });

    for each (auto item in myints)
    {
        const wchar_t* presult = get<1>(item).c_str();
        _putts(presult);
    }

    return 0;
}
\$\endgroup\$
0

2 Answers 2

4
\$\begingroup\$

You don't need std::function, and may do:

template<class C, class F>
bool advfind(C& collection, F fnCompare) 
{
    for (auto& item : collection)
    {
        if (fnCompare(item)) {
            return true;
        }
    }
    return false;
}

or

template<class C, class F>
bool advfind(C& collection, F fnCompare) 
{
    using std::begin;
    using std::end;

    return std::find_if(begin(collection), end(collection), fnCompare) != end(collection);
}
\$\endgroup\$
2
  • \$\begingroup\$ Thanks. I am using this as a learning experience so this is extra helpful. \$\endgroup\$
    – John
    Mar 29, 2016 at 17:05
  • \$\begingroup\$ I miss std::any_of instead of std::find_if :-/ \$\endgroup\$
    – Jarod42
    Mar 29, 2016 at 17:08
2
\$\begingroup\$

advfind looks just like std::any_of, except without the iterator pair:

template <class C, class F>
bool any_of(C& collection, F fn) {
    using std::begin;
    using std::end;
    return std::any_of(begin(collection), end(collection), fn);
}

Also, you don't need to explictly provide the types to this function. Let the compiler deduce your types for you:

bool result = any_of(myints, [](auto &value) {
    if (get<0>(value) == 3)
    {
        get<1>(value) = std::wstring(L"I've changed!");
        return true;
    }

    return false;
});
\$\endgroup\$
4
  • \$\begingroup\$ Thanks. I am using this as a learning experience so this is extra helpful. \$\endgroup\$
    – John
    Mar 29, 2016 at 17:05
  • 1
    \$\begingroup\$ As me, you add const to collection, but the functor modifies value... \$\endgroup\$
    – Jarod42
    Mar 29, 2016 at 17:06
  • \$\begingroup\$ @Jarod42 Ha, habit dies hard. \$\endgroup\$
    – Barry
    Mar 29, 2016 at 17:16
  • \$\begingroup\$ Fortunately I figured out to remove const. ;) That was the easy part. \$\endgroup\$
    – John
    Mar 29, 2016 at 17:27

Your Answer

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