std::optional 的最佳替代方案是从方法返回可选值?(使用 C++98/C++11/C++14)
Best alternative to std::optional to return an optional value from a method? (using C++98/C++11/C++14)
显然,如果使用 C++17 或 boost,std::optional
是从函数返回可选值的最佳选择(另请参阅 GOTW #90)
std::optional<double> possiblyFailingCalculation()
但是,如果一个人坚持使用旧版本(并且无法使用 boost),那么什么是最好的选择?
我看到几个选项:
STL 智能指针(仅限 C++11)
std::unique_ptr<double> possiblyFailingCalculation();
- (+) 与可选用法几乎相同
- (−) 混淆了指向非多态类型或内置类型的智能指针
将其与布尔值配对
std::pair<double,bool> possiblyFailingCalculation();
旧式
bool possiblyFailingCalculation(double& output);
- (−) 与新的 C++11
auto value = calculation()
样式不兼容
- (−) 与新的 C++11
DIY 模板:具有相同功能的基本模板很容易编码,但是实现一个强大的
std::optional<T>
类似模板有什么陷阱吗?引发异常
- (−) 有时"无法计算"是一个有效的返回值。
std::optional
,就像它的boost::optional
父级一样,是一个非常基本的类模板。它是一个bool
,一些存储和一堆方便的成员函数,其中大部分是一行代码和一个断言。
DIY选项绝对是首选。(1) 涉及分配和 (2)、(3) 涉及必须构造一个 T
,即使你想要一个空值 - 这对double
来说根本不重要,但对于更昂贵的类型来说确实很重要。对于 (5),例外不能替代optional
。
您可以随时将您的实现与 Boost 的进行比较。毕竟,这是一个仅包含标头的小型库。
我也会考虑一个哨兵值。
在double
的情况下,NaN
值(std::numeric_limits<double>::quiet_NaN()
)是一个可能的候选值(只有在std::numeric_limits<double>::has_quiet_NaN == true
时才有意义)。
关于这种方法有各种意见(例如,如果更喜欢使用 -ffast-math,请查看 NaN 或 false 作为双精度返回值和双精度的良好哨兵值)。
在特定域中,可能还有其他有意义的哨兵值。
无论如何(不仅对于double
),我会采用/实现类似 markable
(https://github.com/akrzemi1/markable) 的东西来避免魔术值并指示该值可能不存在,并且用户应该检查它的潜在缺失。
有关此方法的其他动机和概述:有效的可选值。
而不是std::optional
,请使用此链接中的tl::optional
:https://github.com/TartanLlama/optional
它具有与std
对应的相同的公共接口,只是它也在 C++98 中编译。
我在生产代码 (C++11) 中使用它并且效果很好!
- C++98,但叮叮当当地说使用nullptr?
- C ++枚举范围无法使用-std=c ++ 98进行编译,但使用-std=c ++ 11可以
- 使用 C++98 标准填充二维静态向量
- 我正在使用dev c ++,但收到错误(C++98'array'必须由构造函数初始化)
- 如何强制Qt QMake项目使用C++98标准?
- 致命错误:unordered_map:没有这样的文件或目录(C++ 98,gcc 4.8.5,使用 CMAKE)
- 关于使用C 11标准编制C 98代码
- 使用 C++11 选项编译 C++98 代码时由于 Boost 标头而导致的不明确重载
- 我需要用c ++ 98重写c ++ 11代码,c ++ 11正在使用lambda函数[&](const Output & o
- 使用固定宽度整数时,C 98 pedtical错误
- 使用 C++98 将矢量的一部分移动(而不是复制)到另一个矢量
- 即使明确指定了98个标准,GCC也使用C 11标准
- 使用 C++98 标准访问地图
- std::optional 的最佳替代方案是从方法返回可选值?(使用 C++98/C++11/C++14)
- 使用标准C++98/03对一个对象进行干净的分配和构造
- Visual c ++ 2013 是否有使用旧方言的选项(如 gcc 的 -std=c++98)?
- 使用SFINAE检查该类是否相同或是从C++98中的另一个模板类派生的
- 使用std::containers存储引用,gnuc++98
- 如何在 <functional> C++11/98 中使用跳过参数
- 将使用C++98标准编写的代码与新的编译器一起编译