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

недавно я провел довольно много времени, понимая сообщение об ошибке при вызове 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:: оператор () (const std:: vector&) const': функция-член уже определена или объявлено

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

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

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

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:vcincludexfunctional(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.

2 ответов


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

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

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&, тогда они будут противоречивыми.


это не ответ, но я просто хочу записать современное решение C++11, где все небольшие помощники привязки устарели в пользу universal 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>.