0

The code is shown here:

class Basket{
public:
/*other contents*/
private:
    // function to compare shared_ptrs needed by the multiset member
    static bool compare(const std::shared_ptr<Quote> &lhs,
        const std::shared_ptr<Quote> &rhs)
    { return lhs->isbn() < rhs->isbn(); }
    // multiset to hold multiple quotes, ordered by the compare member
    std::multiset<std::shared_ptr<Quote>, decltype(compare)*>
        items{compare};
};

We initialize our multiset through an in-class initializer. Commonly we put a same class object in the curly bracket. Why a function can be put here? I can't understand;

It's explained in the book C++ primer like it: The multiset will use a function with the same type as our compare member to order the elements. The multiset member is named items, and we’re initializing items to use our compare function.

I can understand the logic, but what is the syntax used here?

Martin Ba
  • 37,187
  • 33
  • 183
  • 337
  • 1
    It is a [*default member initializer*](https://en.cppreference.com/w/cpp/language/data_members#Member_initialization). – Eljay Nov 18 '22 at 12:04
  • 1
    Which exact piece of syntax is confusing you? Because you seem to explain everything very well. – john Nov 18 '22 at 12:12
  • `items{compare}` is just initialising `items` with `compare`. That's perfectly normal, so I'm not sure why you are confused. See [here](https://en.cppreference.com/w/cpp/container/multiset/multiset) it's constructor (2) – john Nov 18 '22 at 12:13
  • I'v written here: Commonly we put a same class object in the curly bracket. Why a function 'compare' can be put here? thank you, I would check your reference out. – 岁暮音书 Nov 18 '22 at 12:22
  • Do you think the type of the initializer matters? – molbdnilo Nov 18 '22 at 12:26
  • Yeah, how the function `compare` works? which variable is imported in the function? What does the `item` initialized to? – 岁暮音书 Nov 18 '22 at 12:32
  • 1
    `compare` is the ordering function used by `items` - it works like any other function and doesn't "import" anything. See constructor number 2 [here](https://en.cppreference.com/w/cpp/container/multiset/multiset). – molbdnilo Nov 18 '22 at 12:40

2 Answers2

1

items{compare}; is a call to one of the overloads of the constructor of std::mulitset.

Which one of the overloads to use is decided by the compiler from looking at your argument type: compare matches the description of a "comparison function object" (see link), so the second invocation is used.

It is a pointer to a function, taking two values as parameters and returning a boolean is the main point here. That function can then be later called by the multiset object to sort its members. Look up "callback functions" if you want to learn more about this concept. See here for a start: Callback functions in C++

What you're refering to with

Commonly we put a same class object in the curly bracket.

would be using the copy-constructor (no. 6 in the link). Just another way to create the same type of object.

There are questions here on SO about using a constructor with {} vs () if that is part of the confusion: What's the difference between parentheses and braces in c++ when constructing objects

nick
  • 541
  • 1
  • 9
  • 1
    Thank you very much. As a non-native English speaker, this is my first time asking a question on stackoverflow and it was a very good experience, the users are very enthusiastic and patient and perfectly solve my problem. – 岁暮音书 Nov 18 '22 at 13:56
  • sorry, one more question. In the `<>`, the comparison function object has been defined in as the second parameter. Is the constructed object the same when the item is followed by and not followed by `{compare}`? To put it another way, it does not report an error when the comparison function that follows `item` differs from the comparison function in `<>`, don't they conflict? – 岁暮音书 Nov 18 '22 at 14:10
  • @岁暮音书: Glad to hear that :) SO has a reputation for being rough on beginners, but that mainly stems from the flood of lazy, sometime even overbearing questions on the front page. If you show that you put some effort into your question, people are generally nice. – nick Nov 18 '22 at 14:10
  • @岁暮音书: ````<>```` always denotes passing a type, usually to tell a templated object what type you need. Think ````std::vector```` : A vector of integers. Look again: It says ````decltype(compare)*````. ````decltype```` gives you the type of an object (which is of type function in this case) and is used to tell ````std::multiset```` what you actually want to put into it. – nick Nov 18 '22 at 14:15
  • sorry, maybe you misunderstand my meaning. My question is: in the code `std::multiset, decltype(compare)*> items{compare};` , there are two places where the sorting of multiset is specified, one is the second parameter of <>`decltype(compare)*`, and the another one is the constructor of item`{compare}`. So won't they conflict? I've been thinking a lot about it , whether the sorting method in the constructor of `item` only takes effect when the item is initialized, and when extra elements need to be added, the sorting method in <> `decltype(compare)*` is effective. – 岁暮音书 Nov 18 '22 at 16:25
  • I got it! `decltype(ompare)*` just denote the function pointer type passed in multiset and not specify the concrete function. Commonly due to the parameter of `decltype`, It's able to judge the function pointed to. The constructor parameter of `item` really designate the sorting function. – 岁暮音书 Nov 19 '22 at 08:56
1

Commonly we put a same class object in the curly bracket. Why a function can be put here?

What actually happens is that compare when used inside the braces {} decays to a pointer to function due to type decay(as it is a static member function). Then this decayed function pointer is passed as argument to one of the std::multiset's constructor which will make std::multiset to use this compare function as comparator.

//--------------------------------vvvv-------------------->we're passing a pointer to static member function as argument for this first parameter
explicit multiset( const Compare& comp, const Allocator& alloc = Allocator() );
Jason
  • 36,170
  • 5
  • 26
  • 60