patterncppMinor
Maybe type implementation
Viewed 0 times
maybeimplementationtype
Problem
This supposed to implement a
Did I miss anything?
```
#pragma once
#include
#include
#include
namespace ads {
template
class Maybe {
public:
typedef typename ::std::aligned_storage::type storage_type;
typedef T value_type;
private:
storage_type data;
bool is_valid;
inline T* ptr() {
return reinterpret_cast(&data);
}
inline T const* ptr() const {
return reinterpret_cast(&data);
}
public:
Maybe() noexcept : data(), is_valid(false) {}
template
Maybe(U&& v) noexcept(::std::is_nothrow_move_constructible::value) : data(), is_valid(false) {
create(::std::forward(v));
}
Maybe(Maybe const& from) noexcept(::std::is_nothrow_copy_constructible::value) : data(), is_valid(false) {
if (from.is_valid)
create(*from.ptr());
}
Maybe(Maybe&& from) noexcept(::std::is_nothrow_move_constructible::value) : data(), is_valid(false) {
if (from.is_valid)
create(::std::move(*from.ptr()));
}
template
Maybe& operator=(U&& v) noexcept(::std::is_nothrow_move_constructible::value && ::std::is_nothrow_copy_constructible::value && ::std::is_nothrow_assignable::value) {
create(::std::forward(v));
return *this;
}
Maybe& operator=(Maybe const& from) noexcept(::std::is_nothrow_copy_constructible::value && ::std::is_nothrow_assignable::value) {
if (from.is_valid) {
create(*from.ptr());
} else {
destroy();
}
return *this;
}
Maybe& operator=(Maybe&& from) noexcept(::std::is_nothrow_move_constructible::
Maybe type that can either hold a value T or "nothing". It's designed to work well with vectors (that's why I take extra care to noexcept constructors whenever possible). I'm governing the actual data with ::std::aligned_storage. Note: The just member function is a reference to the Haskell Maybe data-constructor Just.Did I miss anything?
```
#pragma once
#include
#include
#include
namespace ads {
template
class Maybe {
public:
typedef typename ::std::aligned_storage::type storage_type;
typedef T value_type;
private:
storage_type data;
bool is_valid;
inline T* ptr() {
return reinterpret_cast(&data);
}
inline T const* ptr() const {
return reinterpret_cast(&data);
}
public:
Maybe() noexcept : data(), is_valid(false) {}
template
Maybe(U&& v) noexcept(::std::is_nothrow_move_constructible::value) : data(), is_valid(false) {
create(::std::forward(v));
}
Maybe(Maybe const& from) noexcept(::std::is_nothrow_copy_constructible::value) : data(), is_valid(false) {
if (from.is_valid)
create(*from.ptr());
}
Maybe(Maybe&& from) noexcept(::std::is_nothrow_move_constructible::value) : data(), is_valid(false) {
if (from.is_valid)
create(::std::move(*from.ptr()));
}
template
Maybe& operator=(U&& v) noexcept(::std::is_nothrow_move_constructible::value && ::std::is_nothrow_copy_constructible::value && ::std::is_nothrow_assignable::value) {
create(::std::forward(v));
return *this;
}
Maybe& operator=(Maybe const& from) noexcept(::std::is_nothrow_copy_constructible::value && ::std::is_nothrow_assignable::value) {
if (from.is_valid) {
create(*from.ptr());
} else {
destroy();
}
return *this;
}
Maybe& operator=(Maybe&& from) noexcept(::std::is_nothrow_move_constructible::
Solution
Creating holes in the type system:
Don't pay for what you don't use:
I would expect constructor to not check for
Missing features:
Style:
You could enter a newline in some places where the line is long.
I think that calling global
operator T& and it's const sibling is probably very undesirable conversion. Why, then, std::string doesn't have operator const char()? The answer is a type system. It meant to be explicit. std::optional uses overloading of operator() and operator->().Don't pay for what you don't use:
I would expect constructor to not check for
is_valid of itself, because it is obvious (you're calling create() from constructor, which does check for validity). In most cases this won't make a difference, but you still should strive for perfection.Missing features:
- swap
- comparison operators
- emplace
value_or, which is I think the most useful. Returns provided default value if there optional is not initialized yet.
- one function that throws when the optional is not initialized yet.
just()is a great candidate.
Style:
You could enter a newline in some places where the line is long.
I think that calling global
std might be somewhat restricting. It is arguable, though.Context
StackExchange Code Review Q#147999, answer score: 2
Revisions (0)
No revisions yet.