Boost lambda :: bind выбор типа возврата - PullRequest
1 голос
/ 30 апреля 2010

Я хотел бы позвонить члену через lambda :: bind. К сожалению, у меня есть два члена с одинаковыми именами, но с разными типами возврата. Есть ли способ помочь lambda :: bind определить правильный тип возвращаемого значения для вызова функции-члена? (связывание отлично работает с явным выводом типа возврата)

#include <vector>
#include <iostream>
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace std;
using namespace boost;

struct A
{
  A (const string & name) : m_name(name) {}

  string &        name ()         { return m_name; }
  const string &  name () const   { return m_name; }

  string m_name;
};

vector<A> av;

int main () 
{
  av.push_back (A ("some name"));

  // compiles fine
  find_if(av.begin(), av.end(), bind<const string &>(&A::name, _1) == "some name");

  // error: call of overloaded 'bind(<unresolved overloaded function type>, const boost::lambda::lambda_functor<boost::lambda::placeholder<1> >&)' is ambiguous
  find_if(av.begin(), av.end(), lambda::bind(&A::name, lambda::_1) == "some name");

  return 0;
}

Ответы [ 2 ]

1 голос
/ 19 мая 2010

Различные типы возврата - красная сельдь. Проблема связана с константной перегрузкой метода (т. Е. У вас будет одна и та же проблема, независимо от того, каковы относительные возвращаемые типы). Эта проблема задокументирована здесь и здесь , и использование указанной формы типа возврата не является рекомендуемым решением (будет работать большую часть времени, за исключением некоторых версия MSVC).

Проблема в том, что получение адреса перегруженной функции-члена (либо перегруженной const, либо перегруженным параметром) неоднозначно, поэтому требуется некоторая дополнительная информация.

Решение состоит в том, чтобы привести указатель функции, который позволяет компилятору точно знать, какую из перегруженных функций вы хотите. Самый простой способ сделать это, как я обнаружил, - это определить типы указателей на функции, так как в противном случае строки получают немного противно Вот пример с вашим кодом (компилирует чистый gcc 4.3.4):

#include <vector>
#include <iostream>
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace std;
using namespace boost;

struct A
{
  A (const string & name) : m_name(name) {}

  string &        name ()         { return m_name; }
  const string &  name () const   { return m_name; }

  string m_name;
};

vector<A> av;

//function pointer for non-const version
typedef string& (A::*NameFuncType)(void);

//function pointer for const version
typedef const string& (A::*NameConstFuncType)(void) const;

int main () 
{
  av.push_back (A ("some name"));

  //'correct' way to call const version w/ boost::bind
  find_if(av.begin(), av.end(), 
    bind(static_cast<NameConstFuncType>(&A::name), _1) == "some name"
  );

  //call for non-const version w/ boost::lambda::bind
  find_if(av.begin(), av.end(), 
     lambda::bind(static_cast<NameFuncType>(&A::name), lambda::_1) == "some name"
  );

  return 0;
}
1 голос
/ 30 апреля 2010

Для документации

"Тип возврата лямбда-функтора, созданного выражением связывания, может быть задан как явно заданный параметр шаблона, как в следующем примере:

bind (target-функция, bind-arguments-list) "

Так что просто сделайте то же самое, что вы сделали с boost: bind.

  find_if(av.begin(), av.end(), lambda::bind<const string &>(&A::name, lambda::_1) == "some name");

PS не проверено

...