C++ Class template with static_assert()
#include <iostream> #include <iomanip> #include <stdexcept> // For standard exception types #include <string> // For to_string() #include <type_traits> class Pool/*w ww . j a v a2 s . c om*/ { protected: double length {1.0}; double width {1.0}; double height {1.0}; public: Pool(double lv, double wv, double hv) : length {lv}, width {wv}, height {hv} {} // Pool() = default; double volume() const { return length*width*height; } }; template <typename T> class Array { static_assert(std::is_default_constructible<T>::value, "A default constructor is required."); private: T* elements; // Array of type T int size; // Number of array elements public: explicit Array(int arraySize); // Constructor Array(const Array& array); // Copy Constructor ~Array(); // Destructor T& operator[](int index); // Subscript operator const T& operator[](int index) const; // Subscript operator-const arrays Array& operator=(const Array& rhs); // Assignment operator int getSize() { return size; } // Accessor for size }; // Constructor template <typename T> // This is a template with parameter T inline Array<T>::Array(int arraySize) try : size {arraySize}, elements {new T[arraySize]} {} catch (std::bad_alloc& ) { std::cerr << "memory allocation failed for Array object creation.\n"; } // Copy constructor template <typename T> inline Array<T>::Array(const Array& array) try : size {array.size}, elements {new T[array.size]} { for (int i {}; i < size; ++i) elements[i] = array.elements[i]; } catch (std::bad_alloc&) { std::cerr << "memory allocation failed for Array object copy.\n"; } // Destructor template <typename T> inline Array<T>::~Array() { delete[] elements; } // Subscript operator template <typename T> inline T& Array<T>::operator[](int index) { if (index >= size) throw std::out_of_range {"Index too large: " + std::to_string(index)}; return elements[index]; } // const subscript operator template <typename T> inline const T& Array<T>::operator[](int index) const { if (index >= size) throw std::out_of_range {"Index too large: " + std::to_string(index)}; return elements[index]; } // Assignment operator template <typename T> inline Array<T>& Array<T>::operator=(const Array& rhs) try { if (&rhs != this) // If lhs != rhs... { // ...do the assignment... if (elements) // If lhs array exists delete[] elements; // release the free store memory size = rhs.size; elements = new T[rhs.size]; for (int i {}; i < size; ++i) elements[i] = rhs.elements[i]; } return *this; // ... return lhs } catch (std::bad_alloc&) { std::cerr << "memory allocation failed for Array assignment.\n"; } int main() { const int nValues {50}; Array<double> values {nValues}; // Class constructor instance created try { for (int i {}; i < nValues; ++i) values[i] = i + 1; // Member function instance created std::cout << "Sums of pairs of elements:"; int lines {}; for (int i {nValues - 1} ; i >= 0 ; i--) std::cout << (lines++ % 5 == 0 ? "\n" : "") << std::setw(5) << values[i] + values[i - 1]; } catch (const std::out_of_range& ex) { std::cerr << "\nout_of_range exception object caught! " << ex.what() << std::endl; } try { const int nPools {10}; Array<Pool> pools {nPools}; // Template instance created for (int i {} ; i <= nPools ; ++i) // Member instance created in loop std::cout << "Pool volume is " << pools[i].volume() << std::endl; } catch (const std::out_of_range& ex) { std::cerr << "\nout_of_range exception object caught! " << ex.what() << std::endl; } }