Quick Links:

bal | bbl | bdl | bsl

Classes | Typedefs | Functions

Component bslstl_equalto
[Package bslstl]

Provide a binary functor conforming to the C++11 equal_to spec. More...

Classes

struct  bsl::equal_to< VALUE_TYPE >
 C++11-compliant binary functor applying operator== More...
struct  bsl::equal_to< void >
 C++11-compliant binary functor applying operator== More...

Typedefs

typedef VALUE_TYPE bsl::equal_to::second_argument_type
typedef bool bsl::equal_to::result_type

Functions

 bsl::equal_to::equal_to ()
 bsl::equal_to::equal_to (const equal_to &original)
 bsl::equal_to::~equal_to ()
equal_to & bsl::equal_to::operator= (const equal_to &)
BSLA_NODISCARD
BSLS_KEYWORD_CONSTEXPR bool 
bsl::equal_to::operator() (const VALUE_TYPE &lhs, const VALUE_TYPE &rhs) const
 bsl::equal_to< void >::equal_to ()
 bsl::equal_to< void >::equal_to (const equal_to &original)
 bsl::equal_to< void >::~equal_to ()
equal_to & bsl::equal_to< void >::operator= (const equal_to &)
template<class TYPE1 , class TYPE2 >
bool bsl::equal_to< void >::operator() (const TYPE1 &lhs, const TYPE2 &rhs) const

Detailed Description

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:
Component bslstl_unorderedmap, Component 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 {
      // This class implements a crude implementation of a set, that will
      // keep a set of values and be able to determine if an element is a
      // member of the set.  Unlike a 'bsl::set' or 'bsl::unordered_set', no
      // hash function or transitive 'operator<' is required -- only a
      // transitive 'EQUALS' operator.
      //
      // The 'TYPE' template parameter must have a public copy constructor
      // and destructor available.
      //
      // The 'EQUALS' template parameter must a function with a function
      // whose signature is
      //..
      //  bool operator()(const TYPE& lhs, const TYPE& rhs) const;
      //..
      // and which returns 'true' if 'lhs' and 'rhs' are equivalent and
      // 'false' otherwise.  This equivalence relation must be transitive and
      // symmetric.  The comparator must have a default constructor and
      // destructor which are public.

      // PRIVATE TYPES
      struct Node {
          TYPE  d_value;
          Node *d_next;
      };

      // DATA
      EQUALS            d_comparator;
      Node             *d_nodeList;
      bslma::Allocator *d_allocator_p;

    private:
      // NOT IMPLEMENTED
      ListSet(const ListSet&);
      ListSet& operator=(const ListSet&);

    public:
      // CREATORS
      explicit
      ListSet(bslma::Allocator *allocator = 0)
      : d_comparator()
      , d_nodeList(0)
      , d_allocator_p(bslma::Default::allocator(allocator))
          // Create an empty "ListSet' using the specified 'allocator', or
          // the default allocator if none is specified.
      {}

      ~ListSet()
          // Release all memory used by this 'ListSet'
      {
          for (Node *node = d_nodeList; node; ) {
              Node *toDelete = node;
              node = node->d_next;

              d_allocator_p->deleteObject(toDelete);
          }
      }

      // MANIPULATOR
      bool insert(const TYPE& value)
          // If 'value' isn't contained in this 'ListSet', add it and return
          // 'true', otherwise, return 'false' with no change to the
          // 'ListSet'.
      {
          if (count(value)) {
              return false;                                         // RETURN
          }

          Node *node = (Node *) d_allocator_p->allocate(sizeof(Node));
          bslma::ConstructionUtil::construct(&node->d_value,
                                             d_allocator_p,
                                             value);
          node->d_next = d_nodeList;
          d_nodeList = node;

          return true;
      }

      int count(const TYPE& value) const
          // Return the number of nodes whose 'd_value' field is equivalent
          // to the specified 'value', which will always be 0 or 1.
      {
          for (Node *node = d_nodeList; node; node = node->d_next) {
              if (d_comparator(node->d_value, value)) {
                  return 1;                                         // RETURN
              }
          }

          return 0;
      }
  };
Then, in main, we declare an instance of ListSet storing ints. The default definition of bsl::equal_to will work nicely:
  ListSet<int> lsi;
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 {
      // This class holds a pointer to zero-terminated string.  It is
      // implicitly convertible to and from a 'const char *'.  The difference
      // between this type and a 'const char *' is that 'operator==' will
      // properly compare two objects of this type for equality of strings
      // rather than equality of pointers.

      // DATA
      const char *d_string;    // held, not owned

    public:
      // CREATOR
      StringThing(const char *string)                             // IMPLICIT
      : d_string(string)
          // Create a 'StringThing' object out of the specified 'string'.
      {}

      // ACCESSOR
      operator const char *() const
          // Implicitly cast this 'StringThing' object to a 'const char *'
          // that refers to the same buffer.
      {
          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 StringThings:
  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 counts results:
  char buffer[10];
  strcpy(buffer, "meow");
  assert(1 == lsst.count(buffer));
  strcpy(buffer, "bite");
  assert(0 == lsst.count(buffer));

Typedef Documentation

template<class VALUE_TYPE = void>
typedef VALUE_TYPE bsl::equal_to< VALUE_TYPE >::second_argument_type [inherited]
template<class VALUE_TYPE = void>
typedef bool bsl::equal_to< VALUE_TYPE >::result_type [inherited]

Function Documentation

template<class VALUE_TYPE = void>
bsl::equal_to< VALUE_TYPE >::equal_to (  )  [inherited]

Create a equal_to object.

template<class VALUE_TYPE = void>
bsl::equal_to< VALUE_TYPE >::equal_to ( const equal_to< VALUE_TYPE > &  original  )  [inherited]

Create a equal_to object. Note that as equal_to is an empty (stateless) type, this operation will have no observable effect.

template<class VALUE_TYPE = void>
bsl::equal_to< VALUE_TYPE >::~equal_to (  )  [inherited]

Destroy this object.

template<class VALUE_TYPE = void>
equal_to& bsl::equal_to< VALUE_TYPE >::operator= ( const equal_to< VALUE_TYPE > &   )  [inherited]

Assign to this object the value of the specified rhs object, and a return a reference providing modifiable access to this object. Note that as equal_to is an empty (stateless) type, this operation will have no observable effect.

template<class VALUE_TYPE = void>
BSLA_NODISCARD BSLS_KEYWORD_CONSTEXPR bool bsl::equal_to< VALUE_TYPE >::operator() ( const VALUE_TYPE &  lhs,
const VALUE_TYPE &  rhs 
) const [inherited]

Return true if the specified lhs compares equal to the specified rhs using the equality-comparison operator, lhs == rhs.

bsl::equal_to< void >::equal_to (  )  [inherited]

Create a equal_to object.

bsl::equal_to< void >::equal_to ( const equal_to< void > &  original  )  [inherited]

Create a equal_to object. Note that as equal_to<void> is an empty (stateless) type, this operation will have no observable effect.

bsl::equal_to< void >::~equal_to (  )  [inherited]

Destroy this object.

equal_to& bsl::equal_to< void >::operator= ( const equal_to< void > &   )  [inherited]

Assign to this object the value of the specified rhs object, and a return a reference providing modifiable access to this object. Note that as equal_to is an empty (stateless) type, this operation will have no observable effect.

template<class TYPE1 , class TYPE2 >
bool bsl::equal_to< void >::operator() ( const TYPE1 &  lhs,
const TYPE2 &  rhs 
) const [inline, inherited]

< Return true if the specified lhs compares equal to the specified rhs using the equality-comparison operator, lhs == rhs. Implemented inline because of compiler errors (AIX, SUN).