3

I am reading C++ Primer about how to define a set. As I look through cppreference about set, I feel confused about the class and constructor signature of set.

From the text:

bool compareIsbn(){....}
multiset<Sales_data, decltype(compareIsbn) *> bookstore(compareIsbn)

Text1:

To use our own operation, we must define the multiset with two types: the key type, Sales_data, and the comparison type, which is a function pointer type that can point to compareIsbn. When we define objects of this type, we supply a pointer to the operation we intend to use. In this case, we supply a pointer to compareIsbn:

So from text1, it seems that I need to put a function pointer in set<Class A, a function pointer>.

But when I look up cppreference, the "signature"(not sure if it's the right word) is:

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class set;

Question1: So the second parameter should be a class?


Text2:

We can write compareIsbn instead of &compareIsbn as the constructor argument because when we use the name of a function, it is automatically converted into a pointer if needed. We could have written &compareIsbn with the same effect.

Also from cppreference constructor of set(I think the textbook is using the first constructor):

set();
explicit set( const Compare& comp, 
              const Allocator& alloc = Allocator() );

Question2: Doesn't the constructor require a function reference? From where it 's saying that it needs a function pointer?


Need some help to understand the "signature" , thanks in advance :D.

PS:

  1. the textbook uses multiset as an example, but the "signature" of set and multiset are quite similar.
  2. I don't know what const Allocator& alloc = Allocator() means, but I think maybe it's something get done automatically? I may ignore it for now.

2 Answers 2

3

This is slightly confused but fairly close to correct.

Type template parameters being specified with 'class' is a historical/syntactical quirk; that actually indicates that parameter is a type. 'typename' is also legal and is semantically identical:

template<typename T>
struct Foo {
    T thing;
}

template<class T>
struct Bar {
    T thing;
}

// Foo and Bar will work identically

In the book's example, the type being passed to the template is "pointer to the type of CompareIsbn"


As for your second question, remember that Compare is a type:

template<typename T>
void Foo(const T& object) { ... }

The template function Foo expects to be passed a const reference to T. If T is a pointer type, then it expects a const reference to a pointer:

Thing* bar = new Thing();
Foo<Thing*>(bar); // This instantiation of the template has signature void (const Thing*&)

In the book's example, Compare is decltype(CompareIsbn)*, so you must pass const decltype(CompareIsbn)*& to the constructor.


cppreference has a page detailing the requirements of the type used for the Compare parameter in the set template, which you might find useful. The short version is that it just has to be a type such that this code works:

// Given Compare comp
// Given Key a, b
bool b = comp(a, b);

There are then some requirements on how that call to operator() must behave.

A function pointer will work in that context, so it's fine. But so would std::function, or any type that implements operator() with the right behaviour. The = std::less<Key> bit in the template declaration is setting the default value for the Compare parameter to be such an object, which just attempts to use Key::operator<.

The Allocator parameter is also a function-like object that is used to create new Key objects when necessary. You very rarely have to provide an explicit allocator; the default implementation will work fine in almost all cases.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you :D. I will come back after I learn Template section.
1

So from text1, it seems that I need to put a function pointer in set<Class A, a function pointer>

Not quite. Yes you need to provide a function pointer to the constructor, but the text tells you that you need to provide a type as an argument to the template. Said type needs to be the type of a function pointer.

So the second parameter should be a class?

The second parameter needs to be a type. Template type parameters are designated by one of two keyword, either class or typename. But they mean the same thing, the argument you provide must be a type.

Doesn't the constructor require a function reference?

No, it requires a reference to an object of the type you gave as an argument. Since you give a function pointer as the type, it needs a reference to a function pointer. That's what it ultimately receives.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.