C++ 如何在C++;?

C++ 如何在C++;?,c++,c++17,stdoptional,C++,C++17,Stdoptional,我试图使用std::optional,但我的代码出现错误。 我已经指定了#include,编译器选项是-std=c++1z,-lc++experimental 如何使用std::experimental::optional 代码如下: #include <experimental/optional> #include <iostream> std::experimental::optional<int> my_div(int x, int y) {

我试图使用std::optional,但我的代码出现错误。
我已经指定了
#include
,编译器选项是
-std=c++1z
-lc++experimental

如何使用
std::experimental::optional

代码如下:

#include <experimental/optional>
#include <iostream>

std::experimental::optional<int> my_div(int x, int y) {
    if (y != 0) {
        int b = x / y;
        return {b};
    }
    else {
        return {};
    }
}

int main() {
    auto res = my_div(6, 2);
    if (res) {
        int p = res.value();
        std::cout << p << std::endl;
    }
}

操作系统:macOS 10.12.5

编译器版本:

Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

好吧,在你发布错误后,我可以调查一下(但你也可以做同样的事情)

简言之

这是苹果在OSX上提供的
可选
的一个问题/错误,但有一个简单的解决方法

发生了什么事

文件
/Library/Developer/CommandLineTools/usr/include/c++/v1/exper‌​imental/optional
将有问题的函数
optional::value
声明为

template <class _Tp>
class optional
    : private __optional_storage<_Tp>
{
  /* ... */

  _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
  constexpr value_type const& value() const
  {
    if (!this->__engaged_)
        throw bad_optional_access();
    return this->__val_;
  }

  _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
  value_type& value()
  {
    if (!this->__engaged_)
        throw bad_optional_access();
    return this->__val_;
  }
  /* ... */
};
// Define availability macros.
#if defined(_LIBCPP_USE_AVAILABILITY_APPLE)
// ...
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
// ...
#else
// ...
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
// ...
#endif
特别是,宏
\u LIBCPP\u AVAILABILITY\u BAD\u OPTIONAL\u ACCESS
\define
d,位于文件
/Library/Developer/CommandLineTools/usr/include/c++/v1/\u config
中,如下所示

template <class _Tp>
class optional
    : private __optional_storage<_Tp>
{
  /* ... */

  _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
  constexpr value_type const& value() const
  {
    if (!this->__engaged_)
        throw bad_optional_access();
    return this->__val_;
  }

  _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
  value_type& value()
  {
    if (!this->__engaged_)
        throw bad_optional_access();
    return this->__val_;
  }
  /* ... */
};
// Define availability macros.
#if defined(_LIBCPP_USE_AVAILABILITY_APPLE)
// ...
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS __attribute__((unavailable))
// ...
#else
// ...
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
// ...
#endif
因此,这是对LLVM的libc++API的一个特定于苹果的更改。正如宏的名字所暗示的那样,原因是苹果没有制造

class bad_optional_access
: public std::logic_error
{
public:
  bad_optional_access() : std::logic_error("Bad optional Access") {}
  virtual ~bad_optional_access() noexcept;
};
可用,因此无法实现依赖它的功能(
可选::value
)。为什么不提供
bad\u optional\u access
(从而违反了标准)尚不清楚,但这可能与库(dylib)必须更改为包含
bad\u optional\u access::~bad\u optional\u access()
有关

如何解决问题

只需使用
optional::operator*

int p = *res;
唯一真正的区别是没有进行访问检查。如果你需要的话,自己动手吧

template<typename T>
T& get_value(std::experimental::optional<T> &opt)
{
  if(!opt.has_value())
    throw std::logic_error("bad optional access");
  return *opt;
}

template<typename T>
T const& get_value(std::experimental::optional<T>const &opt)
{
  if(!opt.has_value())
    throw std::logic_error("bad optional access");
  return *opt;
}
模板
T&get_值(标准::实验::可选和可选)
{
如果(!opt.has_value())
抛出std::logic_错误(“错误的可选访问”);
返回*opt;
}
模板
T常数和get_值(标准::实验::可选常数和可选)
{
如果(!opt.has_value())
抛出std::logic_错误(“错误的可选访问”);
返回*opt;
}

根据gcc 6.3.1进行编译,无任何问题。很可能是您的编译器对C++1z的支持级别不足。很抱歉,我关闭为dupe为时尚早。我发现(至少在我的MAC笔记本上,也运行同一个编译器)有一个文件
/Library/Developer/CommandLineTools/usr/include/c++/v1/experimental/optional
,所以这应该可以用。。。但是,不幸的是,您没有向我们显示错误消息,因此我们可能不得不关闭它。@Walter我添加了错误消息。“为什么不提供bad_optional_访问(从而违反标准)尚不清楚,但这可能与库(dylib)必须更改为包含bad_optional_访问有关::~bad_optional_访问()这是正确的。未来的操作系统版本将提供必要的符号,然后部署到这些版本或更新版本的应用程序将能够使用这些符号。@GregParker您是否与任何权威人士就此事进行过交谈?为什么这样设计,故意制动标准?