Last active
August 2, 2019 15:58
-
-
Save Jules-Baratoux/504ab726599898f849f6 to your computer and use it in GitHub Desktop.
Homework #6 – Array Class Template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <ostream> | |
using std::ostream; | |
#include <stdexcept> | |
using std::invalid_argument; | |
#include <string> | |
using std::string; | |
#include <array> | |
#include <iterator> | |
#include <cassert> | |
#include "utils.h" | |
namespace JulesBaratoux | |
{ | |
template <typename ElemType, | |
int SIZE // should be a std::size_t | |
> | |
struct Array | |
{ | |
typedef ElemType value_type; | |
typedef value_type& reference; | |
typedef const value_type& const_reference; | |
typedef value_type* iterator; | |
typedef const value_type* const_iterator; | |
typedef decltype(SIZE) size_type; | |
// -------------------------------------------------------------------- | |
// SYNOPSYS | |
// -------------------------------------------------------------------- | |
#if -0 | |
// Constructors: | |
Array(void); | |
Array(const Array& source); | |
Array(const value_type source[SIZE]); | |
// Operators: | |
Array operator = (const Array& source); | |
bool operator == (const Array& other) const; | |
bool operator != (const Array& other) const; | |
const_reference operator [] (size_type pos) const; | |
reference operator [] (size_type pos); | |
friend ostream& operator << (ostream& out, const Array& array); | |
// Methodes | |
constexpr size_type size() const; | |
const_iterator begin() const; | |
const_iterator end() const; | |
iterator begin(); | |
iterator end(); | |
#endif | |
// -------------------------------------------------------------------- | |
// IMPLEMENTATION | |
// -------------------------------------------------------------------- | |
// errors | |
static constexpr auto E_BOUND_OVER = "pos > array.size()"; | |
static constexpr auto E_BOUND_UNDER = "pos < 0"; | |
static constexpr auto OSTREAM_START = "["; | |
static constexpr auto OSTREAM_END = "]"; | |
static constexpr auto OSTREAM_SEP = ", "; | |
Array() {} | |
Array(const Array& source) | |
{ | |
for (size_type i = 0; i < SIZE; ++i) | |
{ | |
elements[i] = source[i]; | |
} | |
} | |
Array(const value_type source[SIZE]) | |
{ | |
for (size_type i = 0; i < SIZE; ++i) | |
{ | |
elements[i] = source[i]; | |
} | |
} | |
Array& operator=(const Array& source) | |
{ | |
if (elements != source.elements) | |
{ | |
for (size_type i = 0; i < SIZE; ++i) | |
{ | |
elements[i] = source[i]; | |
} | |
} | |
return *this; | |
} | |
friend ostream& operator<<(ostream& out, const Array& array) | |
{ | |
size_type i = 0; | |
out << OSTREAM_START; | |
while (i < SIZE - 1) | |
{ | |
out << array[i++] << OSTREAM_SEP; | |
} | |
return out << array[i] << OSTREAM_END; | |
} | |
bool operator==(const Array& other) const | |
{ | |
for (size_type i = 0; i < SIZE; ++i) | |
{ | |
if (elements[i] != other.elements[i]) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
bool operator!=(const Array& other) const | |
{ | |
return not (*this == other); | |
} | |
iterator begin() | |
{ | |
return iterator(&elements[0]); | |
} | |
const_iterator begin() const | |
{ | |
return const_iterator(&elements[0]); | |
} | |
iterator end() | |
{ | |
return iterator(&elements[SIZE]); | |
} | |
const_iterator end() const | |
{ | |
return const_iterator(&elements[SIZE]); | |
} | |
reference operator[]( size_type pos ) | |
{ | |
if (pos >= SIZE) | |
{ | |
throw invalid_argument("pos > array.size()"); | |
} | |
else if (pos < 0) | |
{ | |
throw invalid_argument("pos < 0"); | |
} | |
else | |
{ | |
return elements[pos]; | |
} | |
} | |
const_reference operator[]( size_type pos ) const | |
{ | |
if (pos >= SIZE) | |
{ | |
throw invalid_argument(E_BOUND_OVER); | |
} | |
else if (pos < 0) | |
{ | |
throw invalid_argument(E_BOUND_UNDER); | |
} | |
else | |
{ | |
return elements[pos]; | |
} | |
} | |
constexpr size_type size() const | |
{ | |
return SIZE; | |
} | |
struct tests | |
{ | |
static void constructors(void) | |
{ | |
// default constructor | |
Array base; | |
base.elements[0] = 42; // compile time check | |
// copy constructor | |
{ | |
const Array copy(base); | |
assert(copy.elements[0] == base[0]); | |
} | |
// c-style array copy constructor | |
{ | |
const ElemType base[SIZE] = {5}; | |
const Array copy(base); | |
assert(copy.elements[0] == 5); | |
} | |
} | |
static void operator_assign() | |
{ | |
Array array; | |
Array copy; | |
// Assert that arrays are different | |
array.elements[0] = 1; | |
copy.elements[0] = -array.elements[0]; | |
copy = array; | |
assert(copy == array); | |
} | |
static void operator_at() | |
{ | |
Array array; | |
const Array const_array; | |
// normal usage | |
{ | |
array[0] = const_array[0]; | |
assert(array.elements[0] == const_array.elements[0]); | |
} | |
// invalid_argument | |
try | |
{ | |
for (const auto i : {-1, SIZE}) | |
{ | |
volatile size_type trash; | |
// R-value | |
try | |
{ | |
trash = const_array[i]; | |
assert(false); // exception not thrown | |
} | |
catch (const invalid_argument& exception) {} | |
// L-value | |
try | |
{ | |
array[i] = trash; | |
assert(false); // exception not thrown | |
} | |
catch (const invalid_argument& exception) {} | |
} | |
} | |
catch (...) | |
{ | |
assert(false); // bad exception | |
} | |
} | |
static void operator_cmp() | |
{ | |
const ElemType base[SIZE] = {1}; | |
const Array a(base); | |
// == | |
{ | |
Array b(a); | |
assert( (a == b) == true); | |
b[0] = - a[0]; | |
assert( (a == b) == false); | |
} | |
// != | |
{ | |
Array b(a); | |
assert( (a != b) == false); | |
b[0] = -a[0]; | |
assert( (a != b) == true); | |
} | |
} | |
}; | |
private: | |
ElemType elements[SIZE]; | |
friend struct tests; | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <cstdlib> | |
#include <iostream> | |
using std::cout; | |
using std::endl; | |
#include "Array.h" | |
using JulesBaratoux::Array; | |
int main(void) | |
{ | |
// a. Create an Array using the default constructor | |
Array<int, 3> array; | |
// b. Modify all of the elements of the Array created in step a | |
for (auto& c : array) | |
{ | |
++c; | |
} | |
// c. Output all of the elements of the Array created in step a | |
cout << array << endl; | |
// d. Create a const Array from another Array using the copy constructor | |
Array<int, 4>::tests::constructors(); | |
// e. Assign an Array to an existing Array using the copy assignment operator | |
Array<int, 4>::tests::operator_assign(); | |
// f. Compare two Arrays using the equality operator | |
// g. Compare two Arrays using the inequality operator | |
Array<int, 4>::tests::operator_cmp(); | |
// h. Demonstrate an invalid_argument exception being thrown and caught when the | |
// L-value subscript operator is accessed with an index < 0 | |
// i. Demonstrate an invalid_argument exception being thrown and caught when the | |
// L-value subscript operator is accessed with an index >= SIZE | |
// j. Demonstrate an invalid_argument exception being thrown and caught when the | |
// R-value subscript operator is accessed with an index < 0 (you can force the R-value | |
// subscript operator to be called by accessing an element in the const Array). | |
// k. Demonstrate an invalid_argument exception being thrown and caught when the | |
// R-value subscript operator is accessed with an index >= SIZE (you can force the Rvalue | |
// subscript operator to be called by accessing an element in the const Array). | |
Array<int, 4>::tests::operator_at(); | |
return EXIT_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ----------------------------------------------------------------------------- | |
// utils.h | |
// ----------------------------------------------------------------------------- | |
#pragma once | |
// Windows... | |
#ifdef WIN32 | |
# define or || | |
# define and && | |
# define not ! | |
#endif | |
#define warn std::cerr \ | |
<< "warning: In function ‘" << __FUNCTION__ << "’:" << std::endl \ | |
<< "\t" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment