CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Jun 2015
    Posts
    175

    Function objects

    Hello,

    Please consider the code below:

    Code:
    struct No_case { // is lowercase(x) < lowercase(y)?
    	bool operator()(const string& x, const string& y) const
    	{
    		for (int i = 0; i<x.length(); ++i) {
    			if (i == y.length()) return false; // y<x
    			char xx = tolower(x[i]);
    			char yy = tolower(y[i]);
    			if (xx<yy) return true; // x<y
    			if (yy<xx) return false; // y<x
    		}
    		if (x.length() == y.length()) return false; // x==y
    		return true; // x<y (fewer characters in x)
    	}
    };
    
    void sort_and_print(vector<string>& vc)
    {
    	sort(vc.begin(), vc.end(), No_case());
    	for (const auto& s : vc)
    		cout << s << '\n';
    }
    Does it work?
    My issue is with the function object No_case() in the sort algorithm in the sort_and_print function. The bool operator() member function is called by No_case(), while it has two string parameters and No_case is used without any parameters! How can it work please?

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Function objects

    Quote Originally Posted by tomy12 View Post
    Hello,

    Please consider the code below:

    ...

    Does it work?
    Didn't you test it?
    Does it at least compile?
    Victor Nijegorodov

  3. #3
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Function objects

    How can it work please?
    Now is the time for your real introduction to the STL! In VS in your code, click on the word sort, then right click and Go To Definition. This will take you into the source code for sort() in the file algorithm. You'll see that this calls _Sort_unchecked() and that the passed function is the variable _Pred. Repeat the click/Go To Definition. You see that this calls _Sort_unchecked1(). Repeat Go To Definition again to see the code for this function. You should see a call to _Partition_by_median_guess_unchecked(). Repeat the Go To Definition. In the while loop you should see a call to _Pred() with two arguments.

    Code:
    _Pred(*_Pfirst, *(_Pfirst - 1))
    That's how it works. Remember that _Pred is a variable containing the name of the passed comparison function. So when it is used, it is called with 2 arguments - so calls operator() with the matching arguments. That's the beauty of the operator().

    PS
    Does it work?
    Yep!
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  4. #4
    Join Date
    Jun 2015
    Posts
    175

    Re: Function objects

    I changed the code to this:


    Code:
    struct No_case { 
    	  // is lowercase(x) < lowercase(y)?
    
    	bool operator()(const string& x, const string& y) const
    	{
    		for (int i = 0; i<x.length(); ++i)
    		 {
    			if (i == y.length()) return false; // y<x
    			char xx = tolower(x[i]);
    			char yy = tolower(y[i]);
    			if (xx<yy) return true; // x<y
    			if (yy<xx) return false; // y<x
    		 }
    		cout << " Called\n";
    		if (x.length() == y.length()) return false; // x==y
    		return true; // x<y (fewer characters in x)
    	}
    };
    
    void sort_and_print(vector<string>& vs)
    {
    	auto first = vs.begin();
    	auto last = vs.end();
    	
    	sort(first, last, No_case(*first, *(last-1)));
    	for (const auto& s : vs)
    		cout << s << '\n';
    }
    
    int main()
    {
    	vector<string> vs{ "one", "two", "three", "four", "five", "six", "seven" };
    
    	sort_and_print(vs);
    
    	system("pause");
    	return 0;
    }
    It seemingly shouldn't have any issue, but in effect, it has!

  5. #5
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Function objects

    but in effect, it has!
    Yes - it shouldn't compile!
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  6. #6
    Join Date
    Jun 2015
    Posts
    175

    Re: Function objects

    In sort(first, last, No_case(*first, *(last-1)));, No-case is a function object that in its implementation gets two strings. Both *first a, and *(lest-1) are (the first and last) strings. So what is the problem, please?

  7. #7
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Function objects

    But you are passing this to sort as a parameter!

    Code:
    No_case(*first, *(last-1))
    No_case is a struct. You are calling the struct constructor with 2 arguments - but No_case doesn't have a constructor that takes 2 arguments! Try this

    Code:
    sort(first, last, No_case()(*first, *(last-1)));
    This still won't compile but you'll get a different error message. Think about it. Also think about No_case()(*first, *(last-1))). What does this syntax mean?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  8. #8
    Join Date
    Jun 2015
    Posts
    175

    Re: Function objects

    Quote Originally Posted by 2kaud View Post
    In the while loop you should see a call to _Pred() with two arguments.

    Code:
    _Pred(*_Pfirst, *(_Pfirst - 1))
    That's how it works. Remember that _Pred is a variable containing the name of the passed comparison function. So when it is used, it is called with 2 arguments - so calls operator() with the matching arguments. That's the beauty of the operator().
    I found this first while loop:
    Code:
    ...
    while (_First < _Pfirst
    		&& !_DEBUG_LT_PRED(_Pred, *(_Pfirst - 1), *_Pfirst)
    		&& !_Pred(*_Pfirst, *(_Pfirst - 1)))
    		--_Pfirst;
    
    ...
    I think you meant the bold part.
    Yes,
    Code:
    sort(vs.begin(), vs.end(), No_case());
    works as its function body is written. But the question is: sort starts from the beginning to the end. Each time it sends two arguments to the function object (no_case()) for comparison. But according to what mechanism is it done?

    2- I defined a global variable with the value zero and increased by one (++i) inside the body of the bool operator function. It yielded 30 at the end while the function is 20 times called! It shows that the mechanism used calls the function 20 times. Isn't that 30 strange?

  9. #9
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Function objects

    I think you meant the bold part.
    Yes. This shows how No-case is called with 2 parameters.

    Isn't that 30 strange?
    You'll need to post the code used.

    But according to what mechanism is it done?
    If you look at the code, the sort is done using quicksort.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  10. #10
    Join Date
    Jun 2015
    Posts
    175

    Re: Function objects

    This is the code:

    Code:
    #include <C:\Users\Abbasi\Desktop\std_lib_facilities_4.h>
    using namespace std;
    
    int i = 0;
    struct No_case { // is lowercase(x) < lowercase(y)?
    
    	bool operator()(const string& x, const string& y) const
    	{
    		++i;
    		cout << "Called: x = " << x << ", y = " << y << endl;
    		for (int i = 0; i<x.length(); ++i)
    		{
    			if (i == y.length()) return false; // y<x
    			char xx = tolower(x[i]);
    			char yy = tolower(y[i]);
    			if (xx<yy) return true; // x<y
    			if (yy<xx) return false; // y<x
    		}
    
    		if (x.length() == y.length()) return false; // x==y
    		return true; // x<y (fewer characters in x)
    	}
    };
    
    void sort_and_print(vector<string>& vs)
    {
    	sort(vs.begin(), vs.end(), No_case());
    	cout << i << "\n\n";
    	for (const auto& s : vs)
    		cout << s << ' ';
    }
    
    int main()
    {
    	vector<string> vs{ "one", "two", "Three", "four", "five", "vet", "six", "seven" };
    
    	sort_and_print(vs);
    
    	cout << "\n\n";
    
    	system("pause");
    	return 0;
    }
    And this is the output:
    Name:  Capture.jpg
Views: 146
Size:  27.6 KB

    If you look at the output, it's shown that it's the vet-five pair which is sent, then, vet-two, then six-five, six-vet, ...
    If that order is used by the quicksort method so I should look its algorithm up to figure that kind of execution out.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured