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; }