首页 > 解决方案 > boost 是否有一个“紧凑的可选”,其中存在由特殊类型的值编码?

问题描述

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

small_optional<int, -1> 

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

标签: c++booststdoptional

解决方案


标记库是为此唯一目的而创建的:

可标记 1.0.0

一种替代方案,boost::optional<T>它不存储附加标志,但使用特殊指示值bool对内部的“空”状态进行编码。T

用法

你想存储一个可能丢失的东西int吗?你能节省价值-1吗?你可以像这样使用它:

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), "");

你想存储一个可能丢失std::string的 'missing' != 'empty' 吗?你能保留一些包含空字符的字符串值吗,比如std::string("\0\0", 2)?这就是你的做法:

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("\0\0", 2);
  }
  static bool is_marked_value(const std::string& v) { // test if a given value is considered marked
    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), "");

尽管不是 Boost 库,markable 是在Boost 软件许可证 1.0 版下获得许可的。,甚至在 Boosts 自己的可选类型的性能考虑部分中提到:

性能注意事项

[...]

控制大小

[...] 因此,如果对象的大小对您的应用程序至关重要(例如,因为您想利用 CPU 缓存来获得性能)并且您已经确定您愿意以代码清晰度为代价那么它是建议您简单地使用类型int并使用一些“神奇值”来表示非整数,或者使用诸如可标记 库之类的东西。


lib作者的以下博客文章解释了lib的背景和思考过程:


推荐阅读