странная ошибка компилятора при использовании bind2nd (): & quot; функция-член уже определена или объявлена ​​& quot; вместо «ссылка на ссылку»

Я недавно потратил довольно много времени на понимание сообщения об ошибке при звонке func() в этом куске кода:

int main()
{
vector< vector<double> > v;

double sum = 0;
for_each( v.begin(), v.end(),
bind2nd( ptr_fun(func), &sum ) );

return 0;
}

когда func() был объявлен так, код скомпилирован нормально:

void func( vector<double> v, double *sum )
{
}

когда я использовал это объявление (для эффективности), я получил ошибку компилятора:

void func( const vector<double> &v, double *sum )
{
}

Ошибка, которую я ожидал увидеть, была чем-то вроде Ссылка к ссылке ошибка, из-за определения оператора () из binder2nd,

result_type operator()(const argument_type& _Left) const

Вместо этого, к моему удивлению, ошибка, которую дал мне компилятор Visual C ++ (VS2012):

ошибка C2535: ‘void std :: binder2nd<_Fn2> :: operator () (const
станд :: вектор<_Ty> &) const ‘: функция-член уже определена или
объявленный

который я не могу расшифровать.

  • Можете ли вы объяснить, по какому механизму operator() является уже
    определенный
    ?

Полная ошибка, которую я получил, была:

error C2535: 'void std::binder2nd<_Fn2>::operator ()(const std::vector<_Ty> &) const' : member function already defined or declared
with
[
_Fn2=std::pointer_to_binary_function<const std::vector<double> &,double *,void,void (__cdecl *)(const std::vector<double> &,double *)>,
_Ty=double
]
c:\vc\include\xfunctional(319) : see declaration of 'std::binder2nd<_Fn2>::operator ()'
with
[
_Fn2=std::pointer_to_binary_function<const std::vector<double> &,double *,void,void (__cdecl *)(const std::vector<double> &,double *)>
]
c:\consoleapplication1.cpp(31) : see reference to class template instantiation 'std::binder2nd<_Fn2>' being compiled
with
[
_Fn2=std::pointer_to_binary_function<const std::vector<double> &,double *,void,void (__cdecl *)(const std::vector<double> &,double *)>
]

Build FAILED.

8

Решение

Это поведение четко определено (каждый правильный компилятор C ++ не сможет скомпилировать ваш код).

Из стандартного (N3376) раздела D.9.3 по шаблону класса binder2ndэти два определения operator() существовать:

typename Fn::result_type
operator()(const typename Fn::first_argument_type& x) const;

typename Fn::result_type
operator()(typename Fn::first_argument_type& x) const;

Если first_argument_type уже const T&тогда они будут противоречивыми.

6

Другие решения

Это не ответ, но я просто хочу записать современное решение C ++ 11, где все мелкие помощники связывания устарели в пользу универсального std::bind:

#include <functional>
#include <vector>
#include <algorithm>

void func(std::vector<double> const & v, double * sum) { /* ... */ }

int main()
{
std::vector<std::vector<double>> v;
double sum = 0;
std::for_each(v.begin(), v.end(), std::bind(func, std::placeholders::_1, &sum));
}

Вариационные шаблоны C ++ 11, а также более полный набор черт, изменяющих тип, дают std::bind гораздо более сильные способности удержания, чем у предыдущих компонентов в <functional>,

0