mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-14 05:54:50 +00:00
abg-cxx-compat: add simplified version of std::optional
In the absence (but desire) of std::optional<T>, add a simplified version of it to abg_compat:: in case we are compiling with a pre-C++17 standard. Otherwise use std::optional from <optional> directly. This is being used by a later patch and serves as a prerequisite. It only serves the purpose of being a compatibility implementation and does not claim to be complete at all. Just enough for the project's needs. * include/abg-cxx-compat.h (abg_compat::optional): Add new class. * tests/tests-cxx-compat.cc: Add new test cases. Reviewed-by: Giuliano Procida <gprocida@google.com> Signed-off-by: Matthias Maennich <maennich@google.com>
This commit is contained in:
parent
701de3ba5d
commit
c92d724e01
@ -8,8 +8,92 @@
|
||||
#ifndef __ABG_CXX_COMPAT_H
|
||||
#define __ABG_CXX_COMPAT_H
|
||||
|
||||
// C++17 support (via custom implementations if compiled with earlier standard)
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
|
||||
#include <optional>
|
||||
|
||||
#else
|
||||
|
||||
#include <stdexcept> // for throwing std::runtime_error("bad_optional_access")
|
||||
|
||||
#endif
|
||||
|
||||
namespace abg_compat {
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
|
||||
using std::optional;
|
||||
|
||||
#else
|
||||
|
||||
// <optional>
|
||||
|
||||
/// Simplified implementation of std::optional just enough to be used as a
|
||||
/// replacement for our purposes and when compiling with pre C++17.
|
||||
///
|
||||
/// The implementation intentionally does not support a whole lot of features
|
||||
/// to minimize the maintenance effort with this.
|
||||
template <typename T> class optional
|
||||
{
|
||||
bool has_value_;
|
||||
T value_;
|
||||
|
||||
public:
|
||||
optional() : has_value_(false), value_() {}
|
||||
optional(const T& value) : has_value_(true), value_(value) {}
|
||||
|
||||
bool
|
||||
has_value() const
|
||||
{
|
||||
return has_value_;
|
||||
}
|
||||
|
||||
const T&
|
||||
value() const
|
||||
{
|
||||
if (!has_value_)
|
||||
throw std::runtime_error("bad_optional_access");
|
||||
return value_;
|
||||
}
|
||||
|
||||
const T
|
||||
value_or(const T& default_value) const
|
||||
{
|
||||
if (!has_value_)
|
||||
return default_value;
|
||||
return value_;
|
||||
}
|
||||
|
||||
const T&
|
||||
operator*() const
|
||||
{ return value_; }
|
||||
|
||||
T&
|
||||
operator*()
|
||||
{ return value_; }
|
||||
|
||||
const T*
|
||||
operator->() const
|
||||
{ return &value_; }
|
||||
|
||||
T*
|
||||
operator->()
|
||||
{ return &value_; }
|
||||
|
||||
optional&
|
||||
operator=(const T& value)
|
||||
{
|
||||
has_value_ = true;
|
||||
value_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return has_value_; }
|
||||
};
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // __ABG_CXX_COMPAT_H
|
||||
|
@ -12,3 +12,55 @@
|
||||
#include "lib/catch.hpp"
|
||||
|
||||
#include "abg-cxx-compat.h"
|
||||
|
||||
using abg_compat::optional;
|
||||
|
||||
TEST_CASE("OptionalConstruction", "[abg_compat::optional]")
|
||||
{
|
||||
optional<bool> opt1;
|
||||
REQUIRE_FALSE(opt1.has_value());
|
||||
|
||||
optional<bool> opt2(true);
|
||||
REQUIRE(opt2.has_value());
|
||||
CHECK(opt2.value() == true);
|
||||
|
||||
optional<bool> opt3(false);
|
||||
REQUIRE(opt3.has_value());
|
||||
CHECK(opt3.value() == false);
|
||||
}
|
||||
|
||||
TEST_CASE("OptionalValue", "[abg_compat::optional]")
|
||||
{
|
||||
optional<bool> opt;
|
||||
REQUIRE_FALSE(opt.has_value());
|
||||
REQUIRE_THROWS(opt.value());
|
||||
|
||||
opt = true;
|
||||
REQUIRE_NOTHROW(opt.value());
|
||||
CHECK(opt.value() == true);
|
||||
}
|
||||
|
||||
TEST_CASE("OptionalValueOr", "[abg_compat::optional]")
|
||||
{
|
||||
optional<std::string> opt;
|
||||
REQUIRE_FALSE(opt.has_value());
|
||||
|
||||
const std::string& mine = "mine";
|
||||
// Ensure we get a copy of our own value.
|
||||
CHECK(opt.value_or(mine) == mine);
|
||||
|
||||
// Now set the value
|
||||
const std::string& other = "other";
|
||||
opt = other;
|
||||
CHECK(opt.value_or(mine) != mine);
|
||||
CHECK(opt.value_or(mine) == other);
|
||||
}
|
||||
|
||||
TEST_CASE("OptionalDeref", "[abg_compat::optional]")
|
||||
{
|
||||
optional<std::string> opt("asdf");
|
||||
REQUIRE(opt.has_value());
|
||||
|
||||
CHECK(*opt == "asdf");
|
||||
CHECK(opt->size() == 4);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user