/markable

A template for creating optional-like objects with no space overhead

Primary LanguageC++Boost Software License 1.0BSL-1.0

markable Build Status

An alternative to boost::optional<T> which does not store an additional bool flag, but encodes the empty state inside T using a special indicated value.

(This library used to be called compact_optional, but it was renamed to avoid confusion with std::experimental::optional.)

installation

It is a C++11 single-header (header-only) library.

Usage

Do you want to store a possibly missing int? Can you spare value -1? You can use it like this:

using namespace ak_toolkit;
typedef markable<mark_int<int, -1>> opt_int;

opt_int oi;
opt_int o2 (2);

assert (!oi.has_value());
assert (o2.has_value());
assert (o2.value() == 2);

static_assert (sizeof(opt_int) == sizeof(int), "");

Do you want to store a possibly missing std::string, where 'missing' != 'empty'? Can you spare some string values that contain a null character inside, like std::string("\0\0", 2)? This is how you do it:

struct string_marked_value                           // a policy which defines the representaioion of the
  : ak_toolkit::markable_type<std::string>           // empty std::string value
{               
  static std::string empty_value() {                 // create the epty value
    return std::string("\0\0", 2);
  }
  static bool is_empty_value(const std::string& v) { // test if a given value is empty
    return v.compare(0, v.npos, "\0\0", 2) == 0;
  }
};

typedef ak_toolkit::markable<string_marked_value> opt_str;
opt_str os, oE(std::string(""));

assert (!os.has_value());
assert (oE.has_value());
assert (oE.value() == "");

static_assert (sizeof(opt_str) == sizeof(std::string), "");

Cannot spare any value, but still want to use this interface? You can use boost::opitonal or std::experimental::optional at the cost of storage size:

typedef markable<mark_optional<boost::optional<int>>> opt_int;
static_assert (sizeof(opt_int) == sizeof(boost::optional<int>), "");

We also provide a customization for optional bool with the size of a char:

typedef markable<mark_bool> opt_bool;
static_assert (sizeof(opt_bool) == 1, "");

For additional motivation and overview see this post: https://akrzemi1.wordpress.com/2015/07/15/efficient-optional-values/.

Acknowledgemens

The idea of encoding the policy for determining the empty state in a template parameter has been proposed by Vitali Lovich (see https://groups.google.com/a/isocpp.org/d/topic/std-proposals/46J1onhWJ-s/discussion).

Matt Calabrese and Tomasz Kamiński suggested the raw-storage representation for holding optional types with strong invariants.

License

Distributed under the Boost Software License, Version 1.0.