I haven't done much programming in C++, so I figured I'd try making an Optional
class. I'm mainly concerned that I didn't follow good conventions or that I didn't use exceptions well. I know that there are no comments, but for now, let's ignore that.
The idea is that my Optional
class can be used instead of pointers and nullptr
when I need to return an optional value.
optional.h
#pragma once
namespace extra { // I'm putting random library classes/functions in this namespace
template <typename T>
class Optional
{
public:
const static Optional<T> empty;
static Optional<T> of(const T &v);
static Optional<T> of(T *v);
T get() const;
bool hasValue() const;
~Optional() { if (value != nullptr) delete value; }
private:
Optional(T *v) : value{ v } {}
const T *value;
};
template<typename T>
const Optional<T> Optional<T>::empty = Optional::of(nullptr);
#include "optional.impl"
}
optional.impl
#include <stdexcept>
template<typename T>
Optional<T> Optional<T>::of(const T &t) {
return Optional<T>{ new T(t) };
}
template<typename T>
Optional<T> Optional<T>::of(T *t) {
if (t != nullptr) return Optional<T>{ new T(*t) };
return Optional<T>{ nullptr };
}
template<typename T>
bool Optional<T>::hasValue() const {
return value != nullptr;
}
template<typename T>
T Optional<T>::get() const {
if (!hasValue()) throw std::runtime_error("Tried to get the value from an optional that has no value");
return *value;
}
template<typename T>
bool operator==(const Optional<T>& t1, const Optional<T>& t2) {
if (!t1.hasValue() && !t2.hasValue()) return true;
else if (!t1.hasValue() || !t2.hasValue()) return false;
return t1.get() == t2.get();
}
template<typename T>
bool operator!=(const Optional<T>& t1, const Optional<T>& t2) {
return !(t1 == t2);
}