2016-09-15 8 views
1

valarray<double> можно умножить на скаляр. Тем не менее, я получаю сообщение об ошибке, когда хочу умножить на скаляр для valarray<complex<double>>. Мне интересно, есть ли способ сделать это красиво. Вот репродукция проблемы:Умножение valarray комплексных чисел на скаляр

valarray<complex<double>> v1{ { complex<double>{1,0}, complex<double>{2,0}, complex<double>{3,0} } }; 
valarray<complex<double>> v2 = v1 * 2.0; // error 

генерирует Error C2784: 'std::complex<_Other> std::operator *(const std::complex<_Other> &,const std::complex<_Other> &)': could not deduce template argument for 'const std::complex<_Other> &' from 'std::vector<std::complex<double>,std::allocator<_Ty>>'.

Так что я пытался построить свою собственную функцию, чтобы увидеть, если это может быть сделано, и следующие работы:

valarray<complex<double>> VAMult(const valarray<complex<double>> &v, double scalar) 
{ 
    valarray<complex<double>> out(v.size()); 
    for (size_t i = 0; i < v.size(); i++) 
    { 
     out[i] = v[i] * scalar; 
    } 
    return out; 
} 

// makes the following code work: 
valarray<complex<double>> v2 = VAMult(v1, 2.0); 

Но эта реализация сделала бы для очень некрасивого кода, так что я посмотрел в valarray.h и нашел * определение перегрузки:

operator*(const _Ty& _Left, 
     const valarray<_Ty>& _Right) 
{ // return scalar * valarray 
    _VALOP(_Ty, _Right.size(), _Left * _Right[_Idx]); 
} 

#define _VALOP(TYPE, LENGTH, RHS) /* assign RHS(_Idx) to new valarray */ \ 
valarray<TYPE> _Ans(LENGTH); \ 
for (size_t _Idx = 0; _Idx < _Ans.size(); ++_Idx) \ 
    _Ans[_Idx] = RHS; \ 
return (_Ans) 

Мои знания о шаблонах очень ограничены, но можно ли расширить этот класс? Вот моя попытка:

valarray<complex<double>> valarray<complex<double>>::operator*(const double &scalar) 
{ 
    return valarray<complex<double>>{}; 
} 

в результате Error C2039 '*': is not a member of 'std::valarray<std::complex<double>>'

Есть ли способ сделать это так, мои первую строку коды v1 * 2.0 работ или каким-либо близкий компромисс?

ответ

2

Есть ли способ сделать так, чтобы моя первая строка кода v1 * 2.0 работала или какой-то близкий компромисс?

Да: умножьте v1 со сложным скаляром.

Следующий код компилировать

#include <complex> 
#include <valarray> 

int main() 
{ 
    std::valarray<std::complex<double>> v1{ { {1,0}, {2,0}, {3,0} } }; 
    std::valarray<std::complex<double>> v2 = v1 * std::complex<double>{2.0}; 
} 

Проблема заключается в том, что valarray является классом шаблона с operator*() (и подобными операторами), который определяется только по типу шаблона.

Так std::valarray<double> может быть умножено на double скаляр std::valarray<std::complex<double>> может быть умножено на std::complex<double> скаляр, но std::valarray<std::complex<double>> не может быть умножено на double скаляр.

+0

Я мог бы поклясться, что пробовал это, но второе и третье значения были случайными. Это приемлемый компромисс, учитывая мои ограниченные возможности. –

2

Специализация operator* в этом случае является незаконным и не даст вам то, что вы хотите.

Возможно, перегрузка возможна, но добавляется перегрузка до namespace std.

Мы можем сделать:

valarray<complex<double>> v1{ { complex<double>{1,0}, complex<double>{2,0}, complex<double>{3,0} } }; 
valarray<complex<double>> v2 = v1 * complex<double>{2.0}; 

, но я предполагаю, что вы знали, что.

Вы можете использовать named operators и получите:

valarray<complex<double>> v2 = v1 *times* 2.0; 

работать легально.

Вы также можете написать свой собственный буквального конвертер к сложному:

std::complex<double> operator"" _cplx(long double t) { 
    return {(double)std::move(t)}; 
} 

Live example.

Но на самом деле, отлит до complex<double>.

 Смежные вопросы

  • Нет связанных вопросов^_^