Проблема с find_if на карте - PullRequest
1 голос
/ 06 мая 2011

Я пытаюсь использовать std :: find_if на std :: map, ища конкретный объект, который соответствует строке следующим образом:

class MyString
{
public:
    MyString() {}
    MyString(const std::string& x) : m_x(x) {}
    const std::string& value() const
    {
            return m_x;
    }

private:
    std::string m_x;
};

std::map<int,MyString> squaresS;
std::map<int,MyString>::iterator iIt;

squaresS[1] = MyString("1");
squaresS[2] = MyString("4");
squaresS[3] = MyString("9");
const std::string sTarget = "4";

iIt = std::find_if(squaresS.begin(), squaresS.end(),
    boost::bind(std::equal_to<std::string>(),
        boost::bind(&MyString::value,
            boost::bind(&std::map<int,MyString>::value_type::second, _1)),
        sTarget));

if (iIt != squaresS.end())
    std::cout << "Found " << iIt->second.value() << std::endl;
else
    std::cout << "Not Found" << std::endl;

Результат выполнения этого кода не найден;Я ожидал, что Found 4 будет выводиться.Однако, если я делаю примерно то же самое, используя целые числа, то это работает, то есть вывод найден 4:

class MyInteger
{
public:
    MyInteger() {}
    MyInteger(int x) : m_x(x) {}
    int value() const
    {
        return m_x;
    }

private:
    int m_x;
};

std::map<int,MyInteger> squaresI;
std::map<int,MyInteger>::iterator sIt;

squaresI[1] = MyInteger(1);
squaresI[2] = MyInteger(4);
squaresI[3] = MyInteger(9);
int iTarget = 4;

sIt = std::find_if(squaresI.begin(), squaresI.end(),
    boost::bind(std::equal_to<int>(),
        boost::bind(&MyInteger::value,
            boost::bind(&std::map<int,MyInteger>::value_type::second, _1)),
        iTarget));

if (sIt != squaresI.end())
    std::cout << "Found " << sIt->second.value() << std::endl;
else
    std::cout << "Not Found" << std::endl;

Я подозреваю, что это как-то связано с std :: equal_to, но я не уверен, как идтиоб исправлении этого.

Ответы [ 2 ]

3 голосов
/ 06 мая 2011

Вот что вы могли бы сделать:

class MyString
{
public:
    MyString() {}
    MyString(const std::string& x) : m_x(x) {}
    const std::string& value() const
    {
            return m_x;
    }

private:
    std::string m_x;
};

class mystringmatch
{
   MyString _target;
public:
   mystringmatch(const MyString& target):_target(target)
   {
   }

   bool operator()(const std::pair<int, MyString>& src) const
   {
      return src.second.value() == _target.value();
   }
};

int _tmain(int argc, _TCHAR* argv[])
{
   std::map<int,MyString> squaresS;
   std::map<int,MyString>::iterator iIt;

   squaresS[1] = MyString("1");
   squaresS[2] = MyString("4");
   squaresS[3] = MyString("9");
   const std::string sTarget = "4";

   iIt = std::find_if(squaresS.begin(), squaresS.end(), mystringmatch(sTarget));

   if (iIt != squaresS.end())
       std::cout << "Found " << iIt->second.value() << std::endl;
   else
       std::cout << "Not Found" << std::endl;

    return 0;
}

По моему мнению, этот вид кода заставляет людей переходить с C ++ на другие языки. Почти невозможно прочитать.

sIt = std::find_if(squaresI.begin(), squaresI.end(),
    boost::bind(std::equal_to<int>(),
        boost::bind(&MyInteger::value,
            boost::bind(&std::map<int,MyInteger>::value_type::second, _1)),
        iTarget));
1 голос
/ 06 мая 2011

Как отмечали другие, ваш код уже работает для меня (VC ++ 2010 SP1). Тем не менее, есть тривиальное изменение, которое может быть сделано для уменьшения количества вложенных bind s - типы возврата boost::bind (в отличие от std::bind) перегружены всеми реляционными и логическими операторами, включая operator== устранение (или, по крайней мере, смягчение) потребности в адаптерах, подобных std::equal_to<>. Воспользовавшись этим, вы упростите свой код до:

typedef std::map<int, MyString> squares_t;
squares_t::const_iterator iIt = std::find_if(
    squaresS.begin(),
    squaresS.end(),
    boost::bind(
        &MyString::value,
        boost::bind(&squares_t::value_type::second, ::_1)
    ) == sTarget
);

Подробнее см. Boost.Bind документы .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...