Search code examples
c++constructorfunction-pointersmultiset

Multiset declaration with comparator using function pointers


This is an extension of the question asked and answered here: How to define a multiset using a function pointer?

Unfortunately I do not have enough reputation to ask the user with the accepted answer my question as a comment (9 more to go ...), so here I am. Hopefully this was OK to do.

As in that question, I am also working through C++ Primer and am up to the same section. Using the simplified example given in the link above, I'm trying to understand this line:

std::multiset<A, decltype(compareA)*> m1(compareA);

As far as I am aware, this is the syntax for copy constructors. For example, initialising a multiset of integers m1 as a copy of multiset m2 is written as std::multiset<int> m1(m2);.

So what's going on here when we use function pointers? Is this just syntactic sugar to get the function pointer type returned by decltype(compareA)* to point to compareA? I think I'm fundamentally misunderstanding what this line is doing.

As a side note, how am I meant to read the documentation on std::multiset in order to answer this question? I feel like C++ documentation is much less accessible than, for instance, Java documentation, but perhaps I'm just looking in the wrong place.


Solution

  • The line std::multiset<A, decltype(compareA)*> m1(compareA) defines an object named m1 of type std::multiset<A, decltype(compareA)*> and passes compareA as a parameter to its constructor.

    std::multiset's second template paramter is the type of comparator to use. In this case, that's decltype(compareA)*: A pointer to the type of compareA. Probably something like bool (*)(const A&, const A&): Pointer to a function returning bool and accepting two A parameters by const reference. That type by itself can't do any comparisons, you need an actual object of that type that points to a specific function. Normally std::multiset will value-initialize an object of its comparator type, but for a function pointer type that would be a null pointer. To deal with this, std::multiset has a constructor (constructor (1) on that page) that accepts an object of its comparator type that it will use to do its comparisons. Function names are implicitly convertible to a pointer to that function, so passing compareA is equivalent to &compareA.

    Taking this all together, m1's comparator type is "Pointer to a function accepting two As". You pass a pointer to compareA to its constructor, which it will then use to call compareA to do the comparisons it needs.