首页 > 解决方案 > 采用容器类型和比较类型的函数模板

问题描述

下面是一些我想要的代码:

#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;
}

调用者希望看起来像这样:

std::vector<MyType*> vectorFullOfPolymorphicTypes;

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

不幸的是,我目前仅限于使用 Visual Studio 2012,因此不可能使用可变参数模板。任何帮助表示赞赏。这里有一些我还没有弄清楚的错误。

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

标签: c++templates

解决方案


不需要模板模板参数,只需使用typename TContainer

您可以更改模板参数的顺序以避免提供可推导的类型。

您可以使用常规函子来模拟通用 lambda(因此避免提供额外的类型),或者value_type从容器中使用。

C++11 引入了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;
}

用法:

std::vector<MyType*> myypes;

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

推荐阅读