Skip to content

Commit

Permalink
Merge pull request #31 from mapbox/optional
Browse files Browse the repository at this point in the history
[tracking] wip optional
  • Loading branch information
DennisOSRM committed Aug 27, 2014
2 parents 32f9717 + 607c633 commit 4cdd805
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 26 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@ bench: out/bench-variant out/unique_ptr_test out/unique_ptr_test out/recursive_w
./out/recursive_wrapper_test 100000
./out/binary_visitor_test 100000

out/unit: Makefile test/unit.cpp variant.hpp
out/unit: Makefile test/unit.cpp test/optional_unit.cpp optional.hpp variant.hpp
mkdir -p ./out
$(CXX) -o out/unit test/unit.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS)
$(CXX) -o out/optional_unit test/optional_unit.cpp -I./ $(RELEASE_FLAGS) $(COMMON_FLAGS) $(CXXFLAGS) $(LDFLAGS)

test: out/unit
./out/unit
./out/optional_unit

sizes: Makefile variant.hpp
mkdir -p ./out
Expand Down
50 changes: 25 additions & 25 deletions optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,55 @@

namespace mapbox { namespace util {

namespace detail {
struct none_helper{};
}
typedef int detail::none_helper::*none_t ;
none_t const none = (static_cast<none_t>(0)) ;

template<typename T>
class optional {
static_assert(!std::is_reference<T>::value, "optional doesn't support references");

variant<none_t, T> variant_;
struct none_type { };

variant<none_type, T> variant_;

public:
optional() = default;

explicit optional(optional const& rhs) {
variant_ = rhs.variant_;
optional(optional const& rhs) {
if (this != &rhs) { // protect against invalid self-assignment
variant_ = rhs.variant_;
}
}

explicit optional(T const& v) {
optional(T const& v) {
variant_ = v;
}

bool operator!() const {
return variant_.template is<none_t>();
}

T const& get() const {
return variant_.template get<T>();
optional& operator=(optional other) { // note: argument passed by value!
if (this != &other)
{
swap(other);
}
return *this;
}

T& get() {
return variant_.template get<T>();
explicit operator bool() const noexcept {
return variant_.template is<T>();
}

T const& operator *() const { return this->get() ; }
T operator *() { return this->get() ; }
T const& get() const { return variant_.template get<T>(); }
T& get() { return variant_.template get<T>(); }

T const& operator *() const { return this->get(); }
T operator *() { return this->get(); }

optional& operator = ( T const& v ) {
variant_ = v;
return *this;
}

optional& operator = ( optional const& rhs ) {
variant_ = rhs.variant_;
if (this != &rhs)
{
variant_ = rhs.variant_;
}
return *this;
}

Expand All @@ -62,12 +65,9 @@ namespace mapbox { namespace util {
}

void reset() {
variant_ = none;
variant_ = none_type{};
}

};


}
}

Expand Down
71 changes: 71 additions & 0 deletions test/optional_unit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"

#include "optional.hpp"

using namespace mapbox;

struct dummy {
dummy(int _m_1, int _m_2) : m_1(_m_1), m_2(_m_2) {}
int m_1;
int m_2;

};

int main (int argc, char* const argv[])
{
int result = Catch::Session().run(argc, argv);
if (!result) printf("\x1b[1;32m ✓ \x1b[0m\n");
return result;
}

TEST_CASE( "optional can be instantiated with a POD type", "[optiona]" ) {
mapbox::util::optional<double> dbl_opt;

REQUIRE(!dbl_opt);
dbl_opt = 3.1415;
REQUIRE(dbl_opt);

REQUIRE(dbl_opt.get() == 3.1415);
REQUIRE(*dbl_opt == 3.1415);
}

TEST_CASE( "copy c'tor", "[optiona]" ) {
mapbox::util::optional<double> dbl_opt;

REQUIRE(!dbl_opt);
dbl_opt = 3.1415;
REQUIRE(dbl_opt);

mapbox::util::optional<double> other = dbl_opt;

REQUIRE(other.get() == 3.1415);
REQUIRE(*other == 3.1415);
}

TEST_CASE( "const operator*, const get()", "[optiona]" ) {
mapbox::util::optional<double> dbl_opt = 3.1415;

REQUIRE(dbl_opt);

const double pi1 = dbl_opt.get();
const double pi2 = *dbl_opt;

REQUIRE(pi1 == 3.1415);
REQUIRE(pi2 == 3.1415);
}

TEST_CASE( "emplace initialization, reset", "[optional]" ) {
mapbox::util::optional<dummy> dummy_opt;
REQUIRE(!dummy_opt);

// rvalues, baby!
dummy_opt.emplace(1, 2);
REQUIRE(dummy_opt);
REQUIRE(dummy_opt.get().m_1 == 1);
REQUIRE((*dummy_opt).m_2 == 2);

dummy_opt.reset();
REQUIRE(!dummy_opt);

}

0 comments on commit 4cdd805

Please sign in to comment.