2016-07-11 2 views
1

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

#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; 
} 

ответ

2

Забудьте об автоматическом неявном преобразовании (по крайней мере, для контейнеров стандартной библиотеки). Но если вы готовы принять явное преобразование, как в приведенном ниже примере

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; 
} 
3

Всякий раз, когда вы хотите что-то преобразования, функция 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.

4

Вы можете рассмотреть конструктор диапазона std::vector.

std::vector<int> ar3(begin(ar), end(ar)); 
+0

Вам также понадобится 'using std :: begin; используя std :: end; 'если вы хотите, чтобы зависящий от аргумента поиск включал обычные функции. –