我正在寻找可选 ( sizeof small_optional<T> == sizeof (T)
) 的节省空间的实现。所以空虚是用一些特殊的 T 值编码的,例如
small_optional<int, -1>
要求我从不将 -1 存储在 small_optional 中,因此 -1 可以用作魔术值来确定 optional 是否为空。
我正在寻找可选 ( sizeof small_optional<T> == sizeof (T)
) 的节省空间的实现。所以空虚是用一些特殊的 T 值编码的,例如
small_optional<int, -1>
要求我从不将 -1 存储在 small_optional 中,因此 -1 可以用作魔术值来确定 optional 是否为空。
可标记库是为此唯一目的而创建的:
可标记 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的背景和思考过程: