creating container classes that take a function template argument

M

Matt Fioravante

Suppose you wanted to write something like this:

template <typename T, typename CMP=std::less<T> >
class SortedVector : public std::vector<T> {
//stuff
}

Whats the best way to "store" the CMP object?

One could make a private data member CMP _cmp for example.

However this seems to waste space when the comparison is a free function such
as the the default std::less and it will store a function pointer to this
method in _cmp. If you pass it a function, it should not use any storage to
record this compile time constant information.

However if you want to pass it a lambda or some other function object, you may
have to store a copy of said object to retain its state.

So basically what it boils down to is if the function object contains state,
then store that state in the container. If it does not contain state, make the
address of the function a compile time constant in the template argument.

Whats the trick here to do this properly?
 
T

Tobias Müller

Matt Fioravante said:
Suppose you wanted to write something like this:

template <typename T, typename CMP=std::less<T> >
class SortedVector : public std::vector<T> {
//stuff
}

Whats the best way to "store" the CMP object?

One could make a private data member CMP _cmp for example.

However this seems to waste space when the comparison is a free function such
as the the default std::less and it will store a function pointer to this
method in _cmp. If you pass it a function, it should not use any storage to
record this compile time constant information.

I think you are confusing function objects, free functions and classes.
CMP takes a _type_ not a function object, std::less is a class template,
not a free function.
A function object of type std::less<T> is an ordinary object with no data
members. Objects normally don't store pointers to their member functions.

To use std::less, you have to have an object anyway, because operator() is
not static.

In case of empty classes like std::less<T>, it might (or might not) be
beneficial not to store the object in the class, but create a new one every
time you use it.
You can achieve this with a specialization of SortedVector for
std::is_empty said:
However if you want to pass it a lambda or some other function object, you may
have to store a copy of said object to retain its state.

You cannot "pass" a lambda as template parameter of kind "typename", only
its type. The lambda itself has to be passed in the constructor. You have
to manually instanciate the SortedVector template with the type of the
lambda. Actually I don't know if that's even possible.
So basically what it boils down to is if the function object contains state,
then store that state in the container. If it does not contain state, make the
address of the function a compile time constant in the template argument.

Whats the trick here to do this properly?

Same confusion as above. You cannot pass arbitrary objects as template
arguments, only types and a very limited range of primitive objects.

Tobi
 
M

Matt Fioravante

In case of empty classes like std::less<T>, it might (or might not) be
beneficial not to store the object in the class, but create a new one every
time you use it.

You can achieve this with a specialization of SortedVector for
std::is_empty<CMP>::type.

One could also use private inheritance to take advantage of the empty base class optimization. That won't work if your comparison is an ordinary function pointer though.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top