boost 是否有 "compact optional" 存在由类型的特殊值编码?

Does boost have an "compact optional" where presence is encoded by special value of type?

我正在寻找 space 可选 (sizeof small_optional<T> == sizeof (T)) 的高效实现。 所以空是用T的一些特殊值编码的,例如

small_optional<int, -1> 

要求我从不将 -1 存储在 small_optional 中,因此 -1 可以用作魔术值来确定可选值是否为空。

markable 库专为此目的而创建:

Markable 1.0.0

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.

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("[=18=][=18=]", 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>           // 'marked' (special) std::string value
{               
  static std::string marked_value() {                // create the marked value
    return std::string("[=11=][=11=]", 2);
  }
  static bool is_marked_value(const std::string& v) { // test if a given value is considered marked
    return v.compare(0, v.npos, "[=11=][=11=]", 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), "");

虽然不是 Boost 库,但 markable 是在 Boosts 自己的可选类型的 Boost Software License, Version 1.0., and is even referred to from the Performance Considerations 部分下获得许可的:

Performance considerations

[...]

Controlling the size

[...] Therefore, if the size of the objects is critical for your application (e.g., because you want to utilize your CPU cache in order to gain performance) and you have determined you are willing to trade the code clarity, it is recommended that you simply go with type int and use some 'magic value' to represent not-an-int, or use something like markable library.


库的背景和思考过程在库作者的以下博客post中进行了解释: