1

Hello I am trying to understand this piece of code:

vector<int> a = {5, 3, 6, 1, 7};
sort(a.begin(), a.end(), greater<int>());
for(int i : a) cout << i << " "; cout << endl;

Why I need to put parenthesis after the greater. This greater is a structure defined which is like this:

/// One of the @link comparison_functors comparison functors@endlink.
  template<typename _Tp>
    struct greater : public binary_function<_Tp, _Tp, bool>
    {
      _GLIBCXX14_CONSTEXPR
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x > __y; }
    };

This is defined in stl_function.h in c++. Now I think the way it works is that I give a new type or template for this. The comparing file will make an object of this and then through operator overloading, () it will do object_name(int_value_1, int_value_2) and this returns a bool and all is understandable. But why these () when I am sending this in template. Is there some flaw in the way I think this is implemented?

PS: I said object which is a class specific term but I think in structures, it may be called that way in c++.

Shobhit Tewari
  • 535
  • 5
  • 20
  • 4
    The parentheses signify that the constructor is called, i. e. you create an instance of this struct. For comparison: If you wanted to call the operator on such a newly created (temporary) object, it would look like `greater()(10, 12)`. – Aconcagua Jun 13 '21 at 19:34
  • OK makes sense. Then its an object just like new World() in java. It's made but with no name and just passed as the third template? Then typename _Compare contains a reference to an object in memory? – Shobhit Tewari Jun 13 '21 at 19:44
  • 1
    Roughly – apart from the wording not being precise, it's the third function parameter of type of second template parameter, Java's new ressembles much C++'s one, just that in C++ the pointer is explicit, in java implicit, and C++ has no automatic/implicit memory management (garbage collection). – Aconcagua Jun 13 '21 at 19:55
  • 1
    It's not really like `new World()` in Java. Be careful of Java analogies; they often lead to trouble in C++. In C++, `new World()` creates an object on the free store and gives you a pointer to that object. In C++ you'd have to delete that object afterwords. – Pete Becker Jun 13 '21 at 19:56
  • Yeah thank I got it. new World() will be taken up by the garbage collector and is actually address of object while new in c++ gives an object reference and I need to delete it. Thank you man you are awesome. I got it. But is this () a syntax to create objects because otherwise I think it like: greater a; – Shobhit Tewari Jun 13 '21 at 19:58
  • 1
    Not a reference, a pointer... C++ knows both references and pointers, and they differ in many respects (from point of view of the user/coder; technically – if the reference is instantiated at all – you won't be able to distinguish one from another in compiled code). – Aconcagua Jun 13 '21 at 20:00
  • Is this some new syntax to create object greater() – Shobhit Tewari Jun 13 '21 at 20:04
  • 1
    This is general syntax to create temporary objects, unrelated to templates. Like `std::string()`. Similarly for local variables, but in this case you need to drop the parenthteses (`std::greater g/*() skip!*/;`), otherwise it would be a function declaration. On the other hand, if you pass arguments to, you need them again, e. g. `std::vector v(7);`. For comparison: `std::vector* v = new std::vector()` – note the asterisk specifying a pointer type. You usually wouldn't create vectors this way, though. – Aconcagua Jun 13 '21 at 20:07
  • More comfortable: `auto instance = new SomeType();`, avoids type repetition. – Aconcagua Jun 13 '21 at 20:10
  • Thank you sir. It's been a productive discussion. – Shobhit Tewari Jun 13 '21 at 20:12

1 Answers1

3

Why we need to put parenthesis when giving a template type sort(a.begin(), a.end(), greater());

std::greater is a class template. std::greater<int> is an instance of that class template, and is a type (more specifically, a class type). std::greater<int>() is a temporary object (an instance of the type that is the instance of the template). The parentheses are syntax for value initialisation.

It is not possible to pass a type as an argument to a function (however, it would be possible to pass a type as a template argument to a function template). It is possible to pass a temporary object as an argument to a function.

So, we use the parentheses so that an object is created that we pass as an argument.

PS: I said object which is a class specific term but I think in structures, it may be called that way in c++.

If by structure you mean a struct: Structs are classes (that have been declared with the class-key struct).

Instances of all types are objects in C++.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Why we are not passing in an object like in nth_element(iterator, iterator, iterator, comp); – Shobhit Tewari Jun 15 '21 at 09:15
  • In set we cannot pass a function but we can in nth_element why? – Shobhit Tewari Jun 15 '21 at 09:27
  • 1
    @ShobhitTewari `Why we are not passing in an object` We are. `std::greater()` is an object. `In set we cannot pass a function` We can pass a function to the set constructor, if we use a function pointer of compatible type as the template type parameter of the comparator for the set. – eerorika Jun 15 '21 at 09:40