简体   繁体   中英

Upper_bound and lower_bound doesn't compile

I would like to getting the first position and last position of the searched name.

I can't compile this code, although I've seen similar instructions being executed. Gives an error in lower_bound and upper_bound.

Compiled in C++11

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>

using namespace std;

class Client
{
public:
    int id;
    string name;
    int number;
};

int main()
{
    vector<Client>::iterator low;
    vector<Client>::iterator up;
    string s_name;

    Client c1;
    c1.id = 1;
    c1.name = "jhon";
    c1.number = 123;

    Client c2;
    c2.id = 2;
    c2.name = "Mart";
    c2.number = 987;

    Client c3;
    c3.id = 3;
    c3.name = "Jhon";
    c3.number = 256;

    Client c4;
    c4.id = 4;
    c4.name = "Anna";
    c4.number = 851;

    vector<Client> vCli{c1, c2, c3, c4};

    sort(vCli.begin(), vCli.end(), [](Client a, Client b) { return a.name < b.name; });

    s_name = "Jhon";

    low = lower_bound(vCli.begin(), vCli.end(), s_name, [](Client a, Client b) { return a.name < b.name; });
    up = upper_bound(vCli.begin(), vCli.end(), s_name, [](Client a, Client b) { return a.name < b.name; });

    cout << (low - vCli.begin()) << endl;
    cout << (up - vCli.begin()) << endl;

    return 0;
}
C:\Program Files (x86)\CodeBlocks\MinGW\lib\gcc\mingw32\5.1.0\include\c++\bits\predefined_ops.h|144|
error: no match for call to '(main()::<lambda(Client, Client)>) (Client&, const std::__cxx11::basic_string<char>&)'|

The third argument to std::lower_bound and std::upper_bound has to be a Client object or something that can be converted to a Client . If you add a constructor in Client that allows you to construct a Client from a std::string implicitly, your code would work. Here's a quick fix that does not require any other changes to your code.

Client s;
s.name =  "Jhon";

low = lower_bound (vCli.begin(), vCli.end(), s, [](Client a, Client b) { return a.name <  b.name; });
up  = upper_bound (vCli.begin(), vCli.end(), s, [](Client a, Client b) { return a.name <  b.name; });

Here you are.

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>

class Client
{ 
public:
    int id;
    std::string name;
    int number; 
};

int main() 
{
    std::vector<Client> vCli =
    {
        { 1, "Jhon", 123 },
        { 2, "Mart", 987 },
        { 3, "Jhon", 256 },
        { 4, "Anna", 851 },
    };

    std::sort( std::begin( vCli ), std::end( vCli ),
               []( const Client &c1, const Client &c2 )
               {
                    return c1.name < c2.name; 
               } );

    std::string s_name = "Jhon";

    auto low = std::lower_bound( std::begin( vCli ), std::end( vCli ), s_name,
                                []( const Client &c, const std::string &s )
                                {
                                    return c.name < s;
                                } );

    auto up = std::upper_bound( std::begin( vCli ), std::end( vCli ), s_name,
                                []( const std::string &s, const Client &c )
                                {
                                    return s < c.name;
                                } );

    for ( auto first = low; first != up; ++first )
    {
        std::cout << first->id << ", "  
                  << first->name << ", "
                  << first->number << '\n';
    }


    return 0;
}

The program output is

1, Jhon, 123
3, Jhon, 256

Instead of separate calls of std::lower_bound and std::upper_bound you could use one call of std::equal_range . In this case you should define a function object as shown in the demonstrative program below

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>

class Client
{ 
public:
    int id;
    std::string name;
    int number; 
};

struct Compare_by_name
{
    bool operator ()( const Client &c, const std::string &s ) const
    {
        return c.name < s;
    }

    bool operator ()( const std::string &s, const Client &c ) const
    {
        return s < c.name;
    }
};

int main() 
{
    std::vector<Client> vCli =
    {
        { 1, "Jhon", 123 },
        { 2, "Mart", 987 },
        { 3, "Jhon", 256 },
        { 4, "Anna", 851 },
    };

    std::sort( std::begin( vCli ), std::end( vCli ),
               []( const Client &c1, const Client &c2 )
               {
                    return c1.name < c2.name; 
               } );

    std::string s_name = "Jhon";

    auto low_up = std::equal_range( std::begin( vCli ), std::end( vCli ), s_name,
                                    Compare_by_name() );   


    for ( auto first = low_up.first; first != low_up.second; ++first )
    {
        std::cout << first->id << ", "  
                  << first->name << ", "
                  << first->number << '\n';
    }


    return 0;
}

This function object you can use also with std::lower_bound and std::upper_bound instead of their lambda expressions.

As you are searching for a std::string one argument in your comparator needs to be a std::string not a Client :

low = lower_bound(vCli.begin(), vCli.end(), s_name, [](const Client& a, const std::string& b) { return a.name < b; });
up = upper_bound(vCli.begin(), vCli.end(), s_name, [](const std::string& a, const Client& b) { return a < b.name; });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM