C++ Clang不能与std::experimental::optional一起正常工作
似乎clang不能与C++ Clang不能与std::experimental::optional一起正常工作,c++,macos,clang,c++14,optional,C++,Macos,Clang,C++14,Optional,似乎clang不能与std::experimental::optional一起正常工作 考虑下面的例子: #include <experimental/optional> #include <iostream> struct Foo { int bar; }; int main() { Foo foo; std::experimental::optional<Foo> opt = foo; opt.value().bar = 42;
std::experimental::optional
一起正常工作考虑下面的例子:
#include <experimental/optional>
#include <iostream>
struct Foo { int bar; };
int main() {
Foo foo;
std::experimental::optional<Foo> opt = foo;
opt.value().bar = 42;
std::cout << opt.value().bar << std::endl;
}
我没能在bug报告中找到任何关于clang的问题。谁的行为举止得体?我猜g++工作得很好,而clang似乎被窃听了。我错了吗?
EDIT1 实际上,这个错误似乎是由于
坏的\u可选的\u访问的定义造成的,即使这个问题是在使用clang时发生的
EDIT2
没有命令行参数,但-std=c++14
在osx上使用clang执行的测试,只要不使用value
member方法,它就可以很好地编译(因此optional
免费提供)。
这意味着它使用以下方式编译和链接:
opt->bar
而不是:
opt.value().bar
您的代码看起来非常好,opt.value()
应该返回对所包含的值的引用,假设它已启用或引发异常。我们可以看看其中一个例子比后面的例子多,它包括以下段落:
对分离对象使用间接运算符是一种未定义的行为。此行为提供了最大的运行时性能。除了间接运算符,我们还提供成员函数值,如果存在引用,则返回对包含值的引用,否则抛出异常(源自逻辑错误)
如果看一下,它将value()
描述为:
在您的情况下,opt
处于激活状态,如果不是,它应该抛出,我们不会调用未定义的行为
注意,这是在最近几个版本的clang on Wandbox()上编译的
因此,正如Petesh所建议的,这可能是在您的平台上故意的,但确认这一点的唯一方法是提交错误报告
另请注意,正如提案中所述,还有一种可能是短期选择。TL;医生:
@Petesh在评论中的解决方案为我解决了这个问题(发生在从OSX上的源代码构建的Clang 4.0.0中),即在…/实验/可选中添加默认实现(=default
):
std::实验::坏的可选访问::~坏的可选访问()u NOEXCEPT=默认值代码>
详细信息:
根据@Shafik的答案使用解引用运算符并没有按预期工作,因为当前实现在解引用未连接的可选项时提供(void)0
作为值。例如,这会产生一个可选的0,这是不正确的行为。(我也不认为(dis)接合检查应该作为断言来实现,因为断言很可能在发布版本中编译出来,这是出乎意料的。)
要解决(void)0
问题,必须使用正确的行为定义\u LIBCPP\u ASSERT
——如果\u LIBCPP\u DEBUG\u LEVEL
被定义为至少1,那么\u LIBCPP\u ASSERT
将被定义为((x)?(void)0:(\u VSTD::fprintf(stderr,“%s\n”,m),\u VSTD::abort())
,,这将产生预期的行为
但问题是,根据
\u LIBCPP\u DEBUG\u级别
的说法,这是一项正在进行的工作,定义它将产生“相当严重的编译错误”。嗯,我试过了,他们没有撒谎(您使用的是哪种可选实现?是它还是版本?@nicolas libstdc++with g++,libc++with clang.对我来说很好(linux,clang 3.5或3.7,libc++3.5)。您忘了显示命令行。快速浏览标题会告诉我们为什么会出现链接问题-bad\u可选\u如果您调用value()类中有一个虚拟析构函数,这意味着除了vtable之外,还需要实现。在/usr/lib/libc++.dylib
中没有导出的实验性的符号。我同意苹果公司的决定,不将实验性的代码放入它们的代码中在操作系统libc++上,因为这将构成一份合同,出于ABI的原因继续提供它。根据libc++源代码,看起来至少有人会努力从库中删除符号,对我来说,这听起来像是一个积极的决定,但如果你觉得这是一个bug,那么你可以总是向苹果公司提交雷达文件。如果你想解决这个问题,你可以随时输入std::experimental::bad_optional_access::~bad_optional_access()_NOEXCEPT=default;
我喜欢github。比github好得多。@T.C.githug确实很可爱!!:-DHonestly,我不明白你的意图。禁止使用可选的是有道理的。如果不是值成员方法,让客户端使用整个类有意义吗?听起来像个bug。我有没有想过错过了什么?不管怎样,投了赞成票。:-@skypjack我看不出Petesh的推理有明显的缺陷。至于为什么,我不知道。我会假设这是一个bug,提交一个bug报告,看看响应是什么。不,bug报告应该提交给macosx。
opt.value().bar
constexpr T const& optional<T>::value() const;
T& optional<T>::value();
constexpr T const& value()
{
return *this ? storage_.value_ : (throw bad_optional_access(""), storage_.value_);
}