Breaking down this class

It's been quite some time since I've lasted tackled a programming assignment, so forgive me for what might be dumb questions. So I'm trying to get a grasp on this project I have where I'm implementing a templated array with some static assertions and without using STD types. The arrays in my test cases are of fixed lengths.

Basically, my question is, wherever the comments do not say "TODO", those class methods are pretty much set and I don't have to write any code for them to work?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#ifndef ARRAY_HPP
#define ARRAY_HPP

#include <ostream>

template <typename T, std::size_t Length>
class Array
{
public:
    // Static assert that prohibits arrays of length 0
    static_assert(Length != 0, "Array cannot be of length 0";

    Array();
    ~Array();
    Array(const Array& other);
    Array& operator=(const Array& other);

    // Returns the size of the array.
    std::size_t size() const;

    // Returns the first or last element of the array. Ideally, there would be non-const overloads for these too.

    const T& front() const; 
    const T& back() const;

    /**
     * Returns the element of the array that is at the given index.
     * Throws std::out_of_range if index is out of range.
     */
    T& at(std::size_t index);
    const T& at(std::size_t index) const;

    /**
     * Equality checking, i.e. checking if two arrays contain the exact
     * same elements.
     */
    bool operator==(const Array& other) const;
    bool operator!=(const Array& other) const;

private:
    // TODO: Your member variables and helper methods go here.
    
};

/*
 * Returns the element of the array that is at the given index.
 * Causes compilation to fail (with a static assertion) if index is out
 * of range.
 */
template <std::size_t Index, typename T, std::size_t Length>
T& get(Array<T, Length>& array);
template <std::size_t Index, typename T, std::size_t Length>
const T& get(const Array<T, Length>& array);

// Prints each element of the array.
template <typename T, std::size_t Length>
std::ostream& operator<<(std::ostream& os, const Array<T, Length>& array);

#endif  // ARRAY_HPP 
Basically, my question is, wherever the comments do not say "TODO", those class methods are pretty much set and I don't have to write any code for them to work?
A function needs a body. So when there is a function without a body you probably need to implement them which seems pretty much all of them.

It is not too hard. Most of them require just a single line of code and maybe a [static] assert.
Thanks for the reply!

So far I've gotten up to returning the size of the array, which was pretty straightforward. But now I'm stuck on trying to return the first and last elements of the array. I understand how to return them if we were explicitly given the elements of the array, but since my test cases define them in different arrays, how would I do this in a single line of code?

For example, here is one of many test cases
1
2
3
4
5
6
7
8
9
10
11
    Array<int, 4> arr1;

    arr1.at(0) = 2;
    arr1.at(1) = 5;
    arr1.at(2) = 9;
    arr1.at(3) = 15

    std::cout << arr1;
    std::cout << "Front: " << arr1.front() << '\n';
    std::cout << "Back: " << arr1.back() << '\n';


How would I be able to return the value of 15 if it is defined outside of my class? And I guess by extension that means
1
2
    T& at(std::size_t index);
    const T& at(std::size_t index) const;

is the basis of front() and back() since at() is just grabbing the value at a specific index?
You haven't provided the implementation code for the Array class. What's the constructor/destructor code? The private members?
How would I be able to return the value of 15 if it is defined outside of my class?
What is defined outside the class?

And I guess by extension that means
I don't know what you are referring to by 'extension'. And yes you may use at(...) in front() and back().


By the way: When throwing a std::out_of_range see this:

http://www.cplusplus.com/reference/stdexcept/out_of_range/
is the basis of front() and back() since at() is just grabbing the value at a specific index?
Yes. front() returns the first element, and back() returns the last. Use at() to index into your implementation to find those elements, and return them.
To give you a better understanding on how to implement the functions. Here is how the at(...) function may look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename T, std::size_t Length>
class Array
{
public:
...
    /**
     * Returns the element of the array that is at the given index.
     * Throws std::out_of_range if index is out of range.
     */
    T& at(std::size_t index)
    {
      if(index < Length)
        return Value[index];
      else
        throw std::out_of_range{"Out of Range error"};
    }
...

private:
    // TODO: Your member variables and helper methods go here.
    T Value[Length];

};
at is notably slower than [].
you can use at if you are unsure that your index is in range and to throw the error, that is its purpose, but use [] when you know it is safe to do so.
Possible implementations of front() and back():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename T, std::size_t Length>
class Array
{
public:
   ...

   const T& front() const
   {
      return Value[0];
   }
   const T& back() const
   {
      return Value[Length - 1];
   }

   ...

private:
   // TODO: Your member variables and helper methods go here.
   T Value[Length];
   
   ...
};

If at all possible you should use constexpr instead of const, compile-time errors are easier to squash than run-time bugs.
https://stackoverflow.com/questions/14116003/difference-between-constexpr-and-const
I've tried implementing the get() function, but my static assertion throws for this test case when it should not. I also get this error when I try to return Length "binary '[': 'Array<std::string,3>' does not define this operator or a conversion to a type acceptable to the predefined operator".
1
2
3
4
5
    Array<std::string, 3> strs;
    get<0>(strs) = "Hello";
    get<1>(strs) = "there";
    get<2>(strs) = "world";
    std::cout << strs;



Here is my implementation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * Returns the element of the array that is at the given index.
 * Causes compilation to fail (with a static assertion) if index is out
 * of range.
 */
template <std::size_t Index, typename T, std::size_t Length>
T& get(Array<T, Length>& array)
{
	// Static assertion that causes compilation to fail if the given index is out of range.
	static_assert(Index > Length, 'Index is out of range');

	// Retrieve the element
	if (index < Length)
		return array[Length]; // this is where my error points to
}


Also, I'm having trouble trying to print out the elements of the array. I'm thinking of using a for loop, but unsure if I'm right. Here is my implementation. I also receive the same error above.
1
2
3
4
5
6
7
8
9
template <typename T, std::size_t Length>
std::ostream& operator<<(std::ostream& os, const Array<T, Length>& array)
{
        // doesn't work
	for (int i = 0; i < Length; i++) {
		os << array[i];                   // this is where my error points to
        return os;
	}
}
Last edited on
Be careful with spelling, you have index and Index.

Length should be const throughout:

template <typename T, const std::size_t Length>

What subscript do arrays begin with, and end with? That's a hint to figure out what is wrong with this:

return array[Length];
I'm not exactly sure what you're alluding to? Arrays start will 0 as their subscript and depending on their size, the subscript is the last index of the array no? I'm assuming when you say subscript, you mean indexes.
If the array has 10 elements, the first is 0, what is the last? This is another clue to see if one reliases about the variable name.

If the array has 10 elements, you want the 3rd, why return the last +1?

Subscript is the correct term.
Actually there are several problems:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * Returns the element of the array that is at the given index.
 * Causes compilation to fail (with a static assertion) if index is out
 * of range.
 */
template <std::size_t Index, typename T, std::size_t Length>
T& get(Array<T, Length>& array)
{
	// Static assertion that causes compilation to fail if the given index is out of range.
	static_assert(Index < Length, "Index is out of range"); // The assumption is < // A string has ""

	// Retrieve the element
	if (index < Length) // static_assert prevent this
		return array.get(index); // Your array currentlly does not support []
}
Similar:
1
2
3
4
5
6
7
8
9
template <typename T, std::size_t Length>
std::ostream& operator<<(std::ostream& os, const Array<T, Length>& array)
{
        // doesn't work
	for (int i = 0; i < Length; i++) {
		os << ' ' << array.get(i);  // No []  // Consider using whitespace to separate the values
        return os;
	}
}
Last edited on
Topic archived. No new replies allowed.