C++ Operator Overload Lvalues and the Overloaded Subscript Operator

Description

C++ Operator Overload Lvalues and the Overloaded Subscript Operator

 
#include <iostream>
#include <memory>
#include <cstdlib>                     // For random number generator
#include <ctime>                       // For time function
#include <memory>                                     // For smart pointers
#include <vector>                                     // For vector<T>
#include <iostream>
#include <iomanip>
 
class  Pool//  w ww.j a va2  s . c  o m
{
private:
  double length {1.0};
  double width {1.0};
  double height {1.0};
 
public:
  // Constructors
  Pool(double lv, double wv, double hv) : length {lv}, width {wv}, height {hv} {}
 
  Pool() {}                                                             // No-arg constructor
 
  Pool(const Pool& pool)                                                  // Copy constructor
    : length {pool.length}, width {pool.width}, height {pool.height} {}
 
  double volume() const                                                // Function to calculate the volume
  {
    return length*width*height;
  }
 
  // Accessors
  double getLength() const { return length; }
  double getWidth() const { return width; }
  double getHeight() const { return height; }
 
  bool operator<(const Pool& aPool) const;                               // Less-than operator
  bool operator<(double aValue) const;                                 // Compare Pool volume < double value
  Pool operator+(const Pool& aPool) const;                                // Function to add two Pool objects
 
  friend std::ostream& operator<<(std::ostream& stream, const Pool& pool);
};
 
// Less-than comparison for Pool objects
inline bool Pool::operator<(const Pool& aPool) const
{
  return volume() < aPool.volume();
}
 
// Compare the volume of a Pool object with a constant
inline bool Pool::operator<(double aValue) const
{
  return volume() < aValue;
}
 
// Function comparing a constant with volume of a Pool object
inline bool operator<(double aValue, const Pool& aPool)
{
  return aValue < aPool.volume();
}
 
// Operator function to add two Pool objects
inline Pool Pool::operator+(const Pool& aPool) const
{
  // New object has larger length and width, and sum of heights
  return Pool {length > aPool.length ? length : aPool.length,
    width > aPool.width ? width : aPool.width,
    height + aPool.height};
}
 
 
// operator to write Pool objects to a stream
inline std::ostream& operator<<(std::ostream& stream, const Pool& pool)
{
  stream << " Pool(" << std::setw(2) << pool.length << ","
    << std::setw(2) << pool.width << ","
    << std::setw(2) << pool.height << ")";
  return stream;
}
 
 
template <typename T> using ptr = std::shared_ptr<T>;
 
class  Truckload
{
private:
  class  Package
  {
  public:
    ptr<Pool> pPool;                                 // Pointer to the Pool object
    ptr<Package> pNext;                            // Pointer to the next Package
 
    Package(ptr<Pool> pb) : pPool {pb}, pNext {} {}  // Constructor
  };
 
  ptr<Package> pHead;                              // First in the list
  ptr<Package> pTail;                              // Last in the list
  ptr<Package> pCurrent;                           // Last retrieved from the list
  static ptr<Pool> nullPool;                         // Pointer to nullptr
 
public:
  Truckload() {}                                   // No-arg constructor empty truckload
 
  Truckload(ptr<Pool> pPool)                         // Constructor - one Pool
  {
    pHead = pTail = std::make_shared<Package>(pPool);
  }
 
  Truckload(const std::vector< ptr<Pool> >& pools); // Constructor - vector of Pools
 
  ptr<Pool> getFirstPool();                          // Get the first Pool
  ptr<Pool> getNextPool();                           // Get the next Pool
  void  addPool(ptr<Pool> pPool);                     // Add a new Pool
  bool deletePool(ptr<Pool> pPool);                   // Delete a Pool
  ptr<Pool>& operator[](int index) const;        // Overloaded subscript operator
 
  friend std::ostream& operator<<(std::ostream& stream, Truckload& load);
};
 
// Subscript operator
inline ptr<Pool>& Truckload::operator[](int index) const
{
  ptr<Package> p {pHead};                            // Pointer to first Package
  int count {};                                   // Package count
  do {
    if (index == count++)                            // Up to index yet?
      return p->pPool;                                // If so return the pointer to Pool
  } while (p = p->pNext);
  return nullPool;
}
 
// >> operator for output to a stream
inline std::ostream& operator<<(std::ostream& stream, Truckload& load)
{
  load.pCurrent = load.pHead;
  int count {};
  while (load.pCurrent)
  {
    std::cout << *(load.pCurrent->pPool);
    load.pCurrent = load.pCurrent->pNext;
    if (!(++count % 5)) std::cout << std::endl;
  }
  if (count % 5) std::cout << std::endl;
  return stream;
}
 
ptr<Pool> Truckload::nullPool {};                       // Initialize static class member
 
// Constructor
Truckload::Truckload(const std::vector< ptr<Pool> >& pools)
{
  for (auto pPool : pools)
  {
    addPool(pPool);
  }
}
 
// Add a Pool to the list
void Truckload::addPool(ptr<Pool> pPool)
{
  auto pPackage = std::make_shared<Package>(pPool);    // Create a Package
 
  if (pHead)                                          // Check  list is not  empty
    pTail->pNext = pPackage;                          // Add the  new  object  to  the  tail
  else                                                // List is empty
    pHead = pPackage;                                 // so new  object  is the  head
 
  pTail = pPackage;                                   // Store  its address as tail
}
 
// Find the Package containing pPool and delete it from the list
bool Truckload::deletePool(ptr<Pool> pPool)
{
  pCurrent = pHead;                                   // Start at the first pool
  ptr<Package> pPrevious;                             // There's no previous pool to the 1st
  while (pCurrent)
  {
    if (pCurrent->pPool == pPool)                       // Check for identical Pool pointers
    { // We found the pool!
      if (pPrevious)                                  // If there's a previous pool...
      {
        pPrevious->pNext = pCurrent->pNext;           // ...set its next to be the pool after current
      }
      else                                            // It is the first pool...
      {
        pHead = pHead->pNext;                         // ..so make the next the first pool
      }
      pCurrent = nullptr;
      return true;
    }
    pPrevious = pCurrent;                             // Make current the previous pool...
    pCurrent = pCurrent->pNext;                       // ... and the next one current
  }
  return false;
}
 
// Get the first Pool
ptr<Pool> Truckload::getFirstPool()
{
  pCurrent = pHead->pNext;
  return pHead->pPool;
}
 
// Get the next Pool
ptr<Pool> Truckload::getNextPool()
{
  if (!pCurrent)                                      // If there's no current...
    return getFirstPool();                             // ...return the 1st
 
  auto pPackage = pCurrent->pNext;                    // Save the next package
  if (pPackage)                                       // If there is one...
  {
    pCurrent = pPackage;                              // Update current to the next
    return pPackage->pPool;
  }
  pCurrent = nullptr;                                 // If we get to here...
  return nullptr;                                     // ...there was no next
}
 
// Function to generate integral random pool dimensions from 1 to max_size
inline double random(double max_size)
{
  return 1 + static_cast<int>(max_size* static_cast<double>(std::rand()) / (RAND_MAX + 1.0));
}
 
int main()
{
  const double dimLimit {99.0};        // Upper limit on Pool dimensions
  std::srand((unsigned) std::time(0));  // Initialize the random number generator
  Truckload load;
  const int poolCount {20};          // Number of Pool object to be created
 
  // Create poolCount Pool objects
  for (int i {}; i < poolCount; ++i)
    load.addPool(std::make_shared<Pool>(random(dimLimit), random(dimLimit), random(dimLimit)));
 
  std::cout << "The pools are:\n";
  std::cout << load;
  std::cout << "Find largest.\n";
 
  // Find the largest Pool in the  list
  double maxVolume {};
  int maxIndex {};
  int i {};
  while (load[i] )
  {
    if (load[i]->volume() > maxVolume)
    {
      maxIndex = i;
      maxVolume = load[i]->volume();
    }
    ++i;
  }
 
  std::cout << "\nThe largest pool is: ";
  std::cout << *load[maxIndex] << std::endl;
 
  load.deletePool(load[maxIndex]);
  std::cout << "\nAfter deleting the largest pool, the list contains:\n";
  std::cout << load;
 
  load[0] = load[1];
  std::cout << "\nAfter copying the 2nd element to the 1st, the list contains:\n";
  std::cout << load;
  std::cout << "\nAfter making the 2nd element  a pointer to the sum of 3rd and 4th, the list contains:\n";
  load[1] = std::make_shared<Pool>(*load[2] + *load[3]);
  std::cout << load;
}



PreviousNext

Related