Outline
Purpose
Provide a binary functor conforming to the C++11 equal_to
spec.
Classes
- equal_to: C++11-compliant binary functor applying
operator==
Canonical header: bsl_functional.h
- See also
- bslstl_unorderedmap, bslstl_unorderedset
Description
This component provides the C+11 standard binary comparison functor, bsl::equal_to
, that evaluates equality of two VALUE_TYPE
objects through the operator==
. The application of the functor to two different objects o1
and o2
returns true if o1 == o2
. Note that this the for use as keys in the standard unordered associative containers such as bsl::unordered_map
and bsl::unordered_set
. Also note that this class is an empty POD type.
Usage
This section illustrates intended usage of this component.
Example 1: Creating and Using a List Set
Suppose we want to keep a set of a small number of elements, and the only comparison operation we have on the type of the elements is an equality operator. We can keep a singly-linked list of the elements, and exhaustively use the comparison operator to see if a given value exists in the list, forming a primitive set.
First, we define our ListSet
template class:
template <typename TYPE, typename EQUALS = bsl::equal_to<TYPE> >
class ListSet {
struct Node {
TYPE d_value;
Node *d_next;
};
EQUALS d_comparator;
Node *d_nodeList;
private:
ListSet(const ListSet&);
ListSet& operator=(const ListSet&);
public:
explicit
: d_comparator()
, d_nodeList(0)
, d_allocator_p(
bslma::Default::allocator(allocator))
{}
~ListSet()
{
for (Node *node = d_nodeList; node; ) {
Node *toDelete = node;
node = node->d_next;
}
}
bool insert(const TYPE& value)
{
if (count(value)) {
return false;
}
Node *node =
bslma::AllocatorUtil::allocateObject<Node>(d_allocator_p);
d_allocator_p,
value);
node->d_next = d_nodeList;
d_nodeList = node;
return true;
}
int count(const TYPE& value) const
{
for (Node *node = d_nodeList; node; node = node->d_next) {
if (d_comparator(node->d_value, value)) {
return 1;
}
}
return 0;
}
};
Definition bslma_allocator.h:457
void deleteObject(const TYPE *object)
Definition bslma_allocator.h:680
Definition balxml_encoderoptions.h:68
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1243
Then, in main
, we declare an instance of ListSet
storing int
s. The default definition of bsl::equal_to
will work nicely:
Now, we insert several values into our ListSet
. Note that successful insertions return true
while redundant ones return false
with no effect:
assert(true == lsi.insert( 5));
assert(false == lsi.insert( 5));
assert(false == lsi.insert( 5));
assert(true == lsi.insert(11));
assert(true == lsi.insert(17));
assert(true == lsi.insert(81));
assert(true == lsi.insert(32));
assert(false == lsi.insert(17));
Finally, we observe that our count
method successfully distinguishes between values that have been stored in our ListSet
and those that haven't:
assert(0 == lsi.count( 7));
assert(1 == lsi.count( 5));
assert(0 == lsi.count(13));
assert(1 == lsi.count(11));
assert(0 == lsi.count(33));
assert(1 == lsi.count(32));
Example 2: Using Our List Set For a Custom Type
Suppose we want to have a list set containing objects of a custom type. We can declare an operator==
for our custom type, and equal_to
will use that. We will re-use the ListSet
template class from example 1, and create a new custom type.
First, we define a type StringThing
, which will contain a const char *
pointer, it will be a very simple type, that is implicitly castable to or from a const char *
.
class StringThing {
const char *d_string;
public:
StringThing(const char *string)
: d_string(string)
{}
operator const char *() const
{
return d_string;
}
};
Then, we create an operator==
for StringThings
bool operator==(const StringThing& lhs, const StringThing& rhs)
{
return !strcmp(lhs, rhs);
}
Next, in main
, we declare a ListSet
containing StringThing
s:
ListSet<StringThing> lsst;
Then, we insert a number of values, and observe that redundant inserts return false
with no effect:
assert(true == lsst.insert("woof"));
assert(true == lsst.insert("meow"));
assert(true == lsst.insert("arf"));
assert(false == lsst.insert("woof"));
assert(true == lsst.insert("bark"));
assert(false == lsst.insert("meow"));
assert(false == lsst.insert("woof"));
Now, we observe that our count
method successfully distinguishes between values that have been stored in lsst
and those that haven't:
assert(1 == lsst.count("meow"));
assert(0 == lsst.count("woo"));
assert(1 == lsst.count("woof"));
assert(1 == lsst.count("arf"));
assert(0 == lsst.count("chomp"));
Finally, we copy values into a buffer and observe that this makes no difference to count
s results:
char buffer[10];
strcpy(buffer, "meow");
assert(1 == lsst.count(buffer));
strcpy(buffer, "bite");
assert(0 == lsst.count(buffer));