#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
, но не гарантирован, в худшем случае он перемещается.