Невозможно избежать копирования, поскольку std::vector<T>
отличается от типа std::vector<U>
, и у них нет возможности поделиться памятью.Помимо этого, это зависит от того, как данные отображаются.Если сопоставление соответствует неявному преобразованию (например, unsigned short
в bool
), то просто создайте новый вектор, используя начальный и конечный итераторы из старого, и добьетесь цели:
std::vector<bool> newV( oldV.begin(), oldV.end() );
ЕслиОтображение не просто неявное преобразование (и это включает случаи, когда вы хотите что-то проверить; например, что unsigned short
содержит только 0
или 1
), тогда оно становится более сложным.Очевидным решением будет использование std :: transform:
std::vector<TargetType> newV;
newV.reserve( oldV.size() ); // avoids unnecessary reallocations
std::transform( oldV.begin(), oldV.end(),
std::back_inserter( newV ),
TranformationObject() );
, где TranformationObject
- это функциональный объект, который выполняет преобразование, например:
struct ToBool : public std::unary_function<unsigned short, bool>
{
bool operator()( unsigned short original ) const
{
if ( original != 0 && original != 1 )
throw Something();
return original != 0;
}
};
(обратите внимание, что яЯ просто использую эту функцию преобразования в качестве примера. Если единственное, что отличает функцию преобразования от неявного преобразования, - это проверка, то может быть быстрее сначала проверить все значения в oldV
, используя std::for_each
, изатем используйте конструктор из двух итераторов, описанный выше.)
В зависимости от стоимости создания целевого типа по умолчанию может быть быстрее создать новый вектор с правильным размером, а затем перезаписать его:
std::vector<TargetType> newV( oldV.size() );
std::transform( oldV.begin(), oldV.end(),
newV.begin(),
TranformationObject() );
Наконец, еще одной возможностью будет использование boost::transform_iterator
.Что-то вроде:
std::vector<TargetType> newV(
boost::make_transform_iterator( oldV.begin(), TranformationObject() ),
boost::make_transform_iterator( oldV.end(), TranformationObject() ) );
Во многих отношениях это решение, которое я предпочитаю;в зависимости от того, как boost::transform_iterator
был реализован, он также может быть самым быстрым.