Как определить операторы, чтобы массив пользовательских типов мог быть преобразован в массив примитивных типов?
Я даю следующий код, чтобы проиллюстрировать мой вопрос:
#include <vector>
struct Complex
{
int a, b, c;
Complex() : a(3), b(4), c(10) {}
operator int() const { return a+b+c; }
};
int main()
{
Complex abc;
int value = (abc);
Complex def;
def.a = 20;
int value2 = (def);
std::vector<Complex> ar;
ar.push_back(abc);
ar.push_back(def);
std::vector<int> ar2;
ar2.push_back(abc);
ar2.push_back(def);
std::vector<int> ar3;
ar3 = (ar);
}
Это не скомпилируется из-за выражения ar3 = (ar)
, Я объявил оператор преобразования, чтобы Complex
класс может быть использован в где int
ожидается. Могу ли я также заставить его работать для назначения массива Complex
объекты в массиве int
?
Я пытался объявить оператор преобразования не член для массива Complex
, но это не разрешено:
void std::vector<int> operator = (std::vector<Complex> complexArray)
{
std::vector<int> abc;
for(int i=0; i<complexArray.size(); i++)
abc.push_back(complexArray[i]);
return abc;
}
3 ответа
Забудьте об автоматическом неявном преобразовании (по крайней мере, для контейнеров стандартной библиотеки). Но если вы готовы принять явное преобразование, как в следующем примере
const std::vector<int> vi {1, 2, 3, 4, 5};
const std::vector<double> vd = container_cast(vi);
затем реализация container_cast()
полезность следует. Обратите внимание, что он может приводить не только между экземплярами одного и того же контейнера шаблона для разных типов элементов (т.е. std::vector<int>
в std::vector<double>
), но также между разными контейнерами (например, std::vector
в std::list
).
#include <iostream>
#include <vector>
#include <list>
template<class SourceContainer>
class ContainerConverter
{
const SourceContainer& s_;
public:
explicit ContainerConverter(const SourceContainer& s) : s_(s) {}
template<class TargetContainer>
operator TargetContainer() const
{
return TargetContainer(s_.begin(), s_.end());
}
};
template<class C>
ContainerConverter<C> container_cast(const C& c)
{
return ContainerConverter<C>(c);
}
template<class C>
void printContainer(const C& c)
{
std::cout << "{ ";
for( auto x : c )
std::cout << x << ' ';
std::cout << "}" << std::endl;
}
int main()
{
const std::vector<double> vd {2.2, 7.7, 5.5, 1.1, -4.4};
printContainer(vd);
const std::vector<int> vi = container_cast(vd);
printContainer(vi);
const std::list<float> lf = container_cast(vd);
printContainer(lf);
return 0;
}
Вы можете рассмотреть конструктор диапазона std::vector
,
std::vector<int> ar3(begin(ar), end(ar));
Всякий раз, когда вы хотите что-то преобразовать, std::transform
функция может быть полезна для использования.
В вашем случае вы могли бы сделать что-то вроде
// Create the new vector with the same size as the complex vector
std::vector<int> abc(complexArray.size());
std::transform(std::begin(complexVector), std::end(complexVector),
std::begin(abc),
[](Complex const& complex)
{
int result;
// Code here that converts the complex structure to an integer
// and stores the integer in the variable result
return result;
});
После std::transform
вызовите выше (как только вы завершите его с кодом для фактического преобразования структуры) вектор abc
будет содержать все преобразованные целые числа из Complex
структуры в исходном векторе complexVector
,