boost::optional<T>(1.51)提供了一种构建对我的用户非常危险的对象的方法,我想阻止它.假设我有自己的整数类,我想传递一个可选的这样的整数并将其存储在某个类中:
class myint {
public:
int m_a;
myint (int r_a) : m_a(r_a) {
}
};
struct myclass {
boost::optional<myint> content;
myclass (const boost::optional<myint>& arg) : content(arg) {
}
};
Run Code Online (Sandbox Code Playgroud)
现在,这是用户如何使用该类:
myclass(myint(13)); //correct use
myclass(boost::none); //correct use
myclass(myint(0)); //correct use
myclass(0); //INCORRECT use, this easy typo
//equates boost::none which
//is not what the user meant
Run Code Online (Sandbox Code Playgroud)
我想了解这里发生了什么,并防止这种行为.
有趣的是,
myclass(1); //does not compile
Run Code Online (Sandbox Code Playgroud)
boost::none对于我的领域来说,这完全是一个有效的价值,但是boost::none当用户试图输入时,有一个偷偷摸摸的东西0是极其误导和危险的.
意图可能有点隐藏,因为我并没有真正推出一个myint课程而且我真的class myclass没有任何目的.无论如何,我需要向函数发送10个左右的可选ints,并且重复数据删除不起作用.(你可以想象我问你的年龄,身高和财富,还有三个特殊按钮可以检查你是否不想回答问题)
我发布了一个似乎在下面工作的答案(根据Mooing的Duck&Ilonesmiz建议,但更轻).不过,我很高兴听到有关它的评论.
我正在尝试使用c ++ 11功能实现boost :: optional之类的数据结构.这是我到目前为止:
template<typename T>
struct maybe {
bool valid;
union {
T value;
};
maybe() : valid(false) {}
maybe(const T& _v) {
valid = true;
new (&value) T(_v);
}
maybe(const maybe& other) {
if (other.valid) {
valid = true;
new (&value) T(other.value);
}
else valid = false;
}
~maybe() {
if (valid)
value.~T();
}
bool is_valid() { return valid; }
operator T&() {
if (valid) return value;
throw std::bad_exception();
}
};
Run Code Online (Sandbox Code Playgroud)
我利用无限制联合功能为可选值创建一个正确对齐的空间,该空间可以原位存储,而不是动态分配空间.事情主要起作用,除非我想创建一个带引用的<>.例如maybe<int&>导致g ++ 4.7抱怨:
error: …Run Code Online (Sandbox Code Playgroud) 如果我有一个find有时无法找到所需内容的函数,我倾向于使该函数返回一个指针,使得a nullptr指示找不到该东西.
例如
Student* SomeClass::findStudent(/** some criteria. */)
Run Code Online (Sandbox Code Playgroud)
如果Student存在,它将返回指向找到的Student对象的指针,否则它将返回nullptr.
我也看到了boost::optional为这个目的而提倡的.例如,当你想要实现一个可以返回"nothing"的函数时,何时使用boost :: optional以及何时使用std :: unique_ptr?
我的问题是,在这种情况下,没有返回指针是最佳解决方案.即,有可能找不到查询的项目,在这种情况下返回nullptr是一个完美的解决方案.使用类似boost::optional(或任何其他类似解决方案)的东西有什么好处?
请注意,在我的示例中,findStudent只会返回指向由其拥有的对象的指针SomeClass.
假设我们有一个返回 的函数std::optional<A>。那么在基于范围的 for 循环中使用结果的正确方法是什么?最简单的方法不起作用:
for (auto&& e : a().value()) {
// ^--- A&& is returned, so A is destructed
// before loop starts
Run Code Online (Sandbox Code Playgroud)
T optional::value() &&如果我们用代替 ,这个问题就不会存在T&& optional::value() &&,但 STL 和 Boost 都以第二种方式定义它。
处理这种情况的正确方法是什么?我不喜欢我能想到的两种解决方案(沙箱):
std::experimental::optional<A> a() {
// ...
}
void ok1() {
// ugly if type of A is huge
for (auto&& e : A(a().value())) {
// ...
}
}
void ok2() {
// extra variable is not used
// if for …Run Code Online (Sandbox Code Playgroud) 我想创建使用标准 C++ 中的“可选”的头文件。但是,我的标头将从 Visual Studio 2015 和 Visual Studio 2017 项目中引用。
我想要一些东西,例如对于 Visual Studio 2017(带有 C++ 17 lang 功能集),使用 std::optional ,并且在 Visual Studio 2015 中使用 boost::optional 。
我在想这样的事情:
#include <yvals.h>
#if _HAS_CXX17
#include <optional>
template <typename T> using Optional = std::optional<T>;
#else
#include "boost/optional/optional.hpp"
template <typename T> using Optional = boost::optional<T>;
#endif
Run Code Online (Sandbox Code Playgroud)
这样使用'_HAS_CXX17'宏可以吗?有没有更好的方法来做到这一点?
在我看来应该有四种变体 boost::optional
optional<Foo> =>持有一个可变的Foo,可以在初始化后重新分配
optional<Foo const> const =>持有一个const Foo,初始化后无法重新分配
optional<Foo> const =>(应该?)保持一个可变的Foo,但在初始化后不能重新分配
optional<Foo const> =>(应该?)持有一个const Foo,可以在初始化后重新分配
前2个案例按预期工作.但是对optional<Foo> constconst Foo 的解引用,并且optional<Foo const>在初始化之后不允许重新分配(如本问题所述).
const值类型的重新分配是我遇到的具体内容,错误是:
/usr/include/boost/optional/optional.hpp:486:错误:使 'const的富' 为 '这个' 的参数 '富&富::运算符=(const的富&)' 丢弃限定符[-fpermissive]
它发生在这里:
void assign_value(argument_type val,is_not_reference_tag) { get_impl() = val; }
Run Code Online (Sandbox Code Playgroud)
构造之后,实现使用赋值运算符作为参数化可选的类型.它显然不希望左手操作数是一个const值.但是为什么不能将非const可选项重置为新的const值,例如在这种情况下:
optional<Foo const> theFoo (maybeGetFoo());
while (someCondition) {
// do some work involving calling some methods on theFoo
// ...but they should only be const ones
theFoo = maybeGetFoo();
}
Run Code Online (Sandbox Code Playgroud)
一些问题:
我是否正确,希望这在概念上很好,而且无法做到这只是实施中的侥幸?
如果我不编辑boost源,那么在上面的循环中实现逻辑的干净方法是什么,而不是完全废弃boost :: optional?
如果这确实有意义并且我要编辑boost …
c++ boost const-correctness assignment-operator boost-optional
我有几个关于如何boost::optional工作的问题.我们先来这样做:
boost::optional<int> i;
Run Code Online (Sandbox Code Playgroud)
i < 3总是等同于*i < 3(和其他关系运算符类似)?i < 3并且*i < 3未定义?(i还没有设置任何东西)std::cout << i打印?i = 3总是一样的*i = 3.如果是这样,我应该选择哪个?请考虑以下结构:
struct ThingThatWillGoInSharedMemory {
boost::optional<int> opt_value;
};
Run Code Online (Sandbox Code Playgroud)
我正在使用boost :: interprocess来创建共享内存区域.我对boost :: optional的理解是它是一个有区别的联合而不是一个可空的指针.作为反例,使用堆的std :: map和std :: vector之类的东西需要一个显式的分配器来在进程间内存中使用它们,但是boost :: optional,我相当肯定不使用堆并且相当于写作:
struct ThingThatWillGoInSharedMemory {
bool value_initialised;
int value;
}
Run Code Online (Sandbox Code Playgroud)
所以它可以开箱即用.如果有人确认这一点,我会很高兴 - 我没有看到在boost :: optional文档中明确提到了进程间案例,只是暗示了.
我用G ++ 4.7组建了一个前沿设置(虽然目前我还在使用sudo apt-get boost-all-devDebian Wheezy 附带的boost 1.48 ).
我的代码设置在使用的逻辑数据结构是unique_ptr的多维数组.但是multi_array,如果其中有unique_ptr,似乎也无法构造一个空的单元素数组.这样可行:
boost::multi_array<int, 1> arrWorks (boost::extents[1]);
Run Code Online (Sandbox Code Playgroud)
但这不是:
boost::multi_array< unique_ptr<int>, 1> arrFails (boost::extents[1]);
Run Code Online (Sandbox Code Playgroud)
我想编译器的相关抱怨是:
/usr/include/c++/4.7/bits/stl_uninitialized.h:225:从'void std :: uninitialized_fill_n(_ForwardIterator,_Size,const _Tp&)[with _ForwardIterator = std :: unique_ptr*; _Size = unsigned int; _Tp = std :: unique_ptr]'
optional< unique_ptr<...> >即使我应用了这里提供的补丁,我也遇到了一些问题:
https://svn.boost.org/trac/boost/ticket/1841
(注意:找到通过是否可以移动boost :: optional?)
例如:
boost::optional< unique_ptr<int> > optWorks (new int);
// Fails
boost::optional< unique_ptr<int> > optFails (std::move(optWorks));
Run Code Online (Sandbox Code Playgroud)
我觉得我正在做的事情是合法的.事实上,我已经通过将unique_ptr合并到这个项目中,在所有权转移语义方面发现了一些错误.所以我不想说"哦,这太复杂了,只需使用原始指针".
这是支持推动议程吗?它有时间表吗?我可以在此期间使用任何简单的解决方法吗?
使用Boost,我可以创建一个可选的就地:
boost::optional<boost::asio::io_service::work> work = boost::in_place(boost::ref(io_service));
Run Code Online (Sandbox Code Playgroud)
并解除它:
work = boost::none;
Run Code Online (Sandbox Code Playgroud)
有了C++ 14 /实验支持,我可以使用以下方法构建一个可选的就地:
std::experimental::optional<boost::asio::io_service::work> work;
work.emplace(boost::asio::io_service::work(io_service));
Run Code Online (Sandbox Code Playgroud)
但我对如何脱离它感到茫然......
boost-optional ×10
c++ ×10
boost ×3
c++11 ×3
c++14 ×1
c++17 ×1
maybe ×1
optional ×1
std ×1
stdoptional ×1
unique-ptr ×1