Как определить операторы, чтобы массив пользовательских типов мог быть преобразован в массив примитивных типов?

Я даю следующий код, чтобы проиллюстрировать мой вопрос:

#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,

Другие вопросы по тегам