c++ - 我如何在 C++ 中使用 std::optional?

标签 c++ c++17 stdoptional

我正在尝试使用 std::optional 但我的代码引发了错误。
我指定了 #include <experimental/optional>和编译器选项是 -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;
    }
}

错误信息:

optional.cpp:17:21: error: call to unavailable member function 'value': 
        int p = res.value();
                ~~~~^~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/experimental/optional:525:17: note: candidate function has been explicitly made unavailable
    value_type& value()
                ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/experimental/optional:517:33: note: candidate function has been explicitly made unavailable
    constexpr value_type const& value() const
                                ^
1 error generated.

操作系统: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

最佳答案

好的,在您发布错误后,我可以调查一下(但您也可以这样做)。

简而言之

这是 optional 的问题/错误由 Apple 在 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_;
  }
  /* ... */
};

仅运行预处理器(编译器选项 -E)显示宏扩展为

#define _LIBCPP_INLINE_VISIBILITY \
  __attribute__ ((__visibility__("hidden"), __always_inline__))
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS \
  __attribute__((unavailable))

特别是宏 _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS#define d 在文件中 /Library/Developer/CommandLineTools/usr/include/c++/v1/__config作为

// 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

因此,这是 Apple 特定于 LLVM 的 libc++ API 的更改。正如宏的名字所暗示的那样,原因是 Apple 没有制作

class bad_optional_access
: public std::logic_error
{
public:
  bad_optional_access() : std::logic_error("Bad optional Access") {}
  virtual ~bad_optional_access() noexcept;
};

可用,因此无法实现依赖于它的功能 ( optional::value )。为什么 bad_optional_access未提供(从而违反标准)尚不清楚,但这可能与必须更改库 (dylib) 以包含 bad_optional_access::~bad_optional_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;
}

关于c++ - 我如何在 C++ 中使用 std::optional?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44217316/

相关文章:

c++ - 为什么 C++17 结构化绑定(bind)不使用 {}?

c++ - 为什么允许 std::optional 与值进行比较?

c++ - nullptr、{} 和 nullopt 之间的区别

c++ - 套接字发送数据但 recv 程序不能正常工作

c++ - 我什么时候应该使用 std::any

c++ - 来自 std::any 的 std::is_reference

c++ - C++基于范围的for循环会调用迭代器的析构函数吗?

c++ - 与返回类型无关的 value_or 的替代方法

c++ - 是否可以在 Go 中使用类似 "freopen"的结构?

c++ - 如何从接受器循环中的 ENFILE 中恢复