Шаблон функции, принимающий тип контейнера и тип сравнения

#c #templates

#c #шаблоны

Вопрос:

Ниже приведен некоторый код, который я хотел бы:

  • возьмите контейнер
  • возьмите тип
  • возвращает новый контейнер того же типа, содержащий объекты (ptr) из исходного контейнера, которые не соответствуют типу типа сравнения
 #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 TContaineramp; container) //, TObject object)
{
    TContainer found;
    auto itemIt = container.begin(), end = container.end();
    auto compare = [](const TObjectamp; 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
  

Ответ №1:

Нет необходимости в параметре шаблона шаблона, просто используйте typename TContainer :

Вы можете изменить порядок параметров шаблона, чтобы избежать предоставления выводимых типов.

Вы можете использовать обычный функтор для имитации общего лямбда-выражения (и поэтому избегать предоставления дополнительного типа) или использовать value_type из контейнера.

C 11 представляет std::copy_if .

 template <class TObject, typename TContainer>
TContainer FindItemsNotMatching(const TContaineramp; container)
{
    TContainer found;
    auto predicate = [](const typename TContainer::value_typeamp; 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);
  

Комментарии:

1. copy_if отлично

2. Можете ли вы подтвердить, что ‘found’ использует оптимизацию возвращаемого значения, чтобы избежать копирования?

3. NRVO возможен found , но не гарантирован, в худшем случае он перемещается.