Rich von Lehe
Rich von Lehe

Reputation: 1552

Function template taking a container type and a compare type

Below is some code that I would like to:

#include <typeinfo>

// Algorithm wrapper around find_if that takes an STL collection and returns
// the subset in that collection not matching the compare.  Rely on return-value
// optimization for the returned container.
//
template< template<class, class> class TContainer, class TObject> //, class TCompare>
TContainer FindItemsNotMatching(const TContainer& container) //, TObject object)
{
    TContainer found;
    auto itemIt = container.begin(), end = container.end();
    auto compare = [](const TObject& item) -> bool
    {
        return typeid(*item) != typeid(TCompare);
    };

    while (itemIt != end)
    {
        itemIt = std::find_if(itemIt,
                              allEntities.end(),
                              compare);
        if (itemIt != end)
        {
            found.push_back(*itemIt);
        }
    }

    return found;
}

The caller would look hopefully like this:

std::vector<MyType*> vectorFullOfPolymorphicTypes;

std::vector<MyType*> notMatching = FindItemsNotMatching<std::vector<MyType*>, TypeDerivedFromMyType> (vectorFullOfPolymorphicTypes);

Unfortunately, I'm limited to using only Visual Studio 2012 at the moment, so no variadic templates are possible. Any help is appreciated. Here are some errors that I haven't figured out.

UdfAlgorithm.cpp:9: error: C3205: argument list for template template parameter 'TContainer' is missing

Upvotes: 0

Views: 62

Answers (1)

Jarod42
Jarod42

Reputation: 218323

No need of template template parameter, just use typename TContainer:

You might change order of template parameter to avoid to provide deducible types.

You might use regular functor to simulate generic lambda (and so avoid to provide extra type), or use value_type from container.

C++11 introduces std::copy_if.

template <class TObject, typename TContainer>
TContainer FindItemsNotMatching(const TContainer& container)
{
    TContainer found;
    auto predicate = [](const typename TContainer::value_type& item) -> bool
    {
        return typeid(*item) != typeid(TObject);
    };
    std::copy_if(container.begin(), container.end(), std::back_inserter(found), predicate);

    return found;
}

Usage:

std::vector<MyType*> myypes;

std::vector<MyType*> notMatching = FindItemsNotMatching<SomeDerivedType>(myTypes);

Upvotes: 3

Related Questions