Использование std :: transform и tr1 :: bind для преобразования вектора std :: complex

Учитывая std :: vector из std :: complex, я хотел бы преобразовать его в вектор, содержащий только реальную часть комплекса, разделенную на некоторый постоянный коэффициент. Прямо сейчас я так делаю:

std::vector<std::complex<double> > vec;
std::vector<double> realVec;
double norm = 2.0;
...
for (std::vector<std::complex<double> >::iterator it = vec.begin(), itEnd = vec.end(); it != itEnd; ++it)
    realVec.push_back((*it).real() / norm);

Это, конечно, отлично работает, но я ищу способ использовать std :: transform для того же. Я пытался:

transform(vec.begin(), vec.end(), back_inserter(realVec), tr1::bind(divides<double>(), tr1::bind(&complex<double>::real, tr1::placeholders::_1), norm));

Но это не сработает. У меня такая ошибка:

erreur: no matching function for call to ‘bind(<unresolved overloaded function type>, std::tr1::_Placeholder<1>&)’|

Я не понимаю, почему существует «неразрешенный тип перегруженной функции».

Может ли кто-нибудь объяснить мне, что не так?


person OlivierB    schedule 19.04.2011    source источник
comment
Я знаю, что это, вероятно, ересь, но ИМО версия, использующая цикл for, намного яснее.   -  person Chris Card    schedule 19.04.2011


Ответы (2)


К сожалению, вы не можете этого сделать, по крайней мере, напрямую. Типы функций-членов стандартной библиотеки (например, complex<double>::real) остаются неуказанными, поэтому реализация может предоставлять дополнительные перегрузки, а функции, которые есть, могут иметь дополнительные параметры с аргументами по умолчанию.

По сути, не существует переносимого способа получить адрес функции-члена стандартной библиотеки.

Лучше всего написать вспомогательную функцию:

template <typename T>
T get_real(const std::complex<T>& c) { return c.real(); }

и привяжите к этому:

std::tr1::bind(&get_real<double>, std::tr1::placeholders::_1)
person James McNellis    schedule 19.04.2011

std::complex<>::real() перегружен (см. C ++ 11 [сложный]).

template <typename T>
class complex {
    // ...
    T real() const; // getter
    void real( T ); // setter
    // ...
};

C ++ требует разрешения неоднозначности, когда вы берете адрес перегруженной функции. В вашем случае вы должны сказать:

tr1::bind( static_cast<double(std::complex<double>::*)()const>( &std::complex<double>::real ),
           tr1::placeholders::_1 )

Да, это некрасиво.

person Marc Mutz - mmutz    schedule 19.04.2011
comment
К сожалению, это не так просто, поскольку реализация может предоставлять дополнительные перегрузки или добавлять дополнительные параметры с аргументами по умолчанию к существующим перегрузкам. :( - person James McNellis; 19.04.2011
comment
@ Джеймс: конечно, но OP спросил почему он получил эту ошибку. Легальный язык хорош, но говоря, что вы не можете назвать типы функций-членов классов в пространстве имен std, упускает из виду вопрос OP, IMO, который является разрешением неоднозначности, необходимым при получении адреса перегруженной функции. - person Marc Mutz - mmutz; 20.04.2011