std::variant<>::get()在Apple LLVM 10.0下无法编译

19

我正在尝试使用C++17的std::variant类型,并尝试编译cppreference中get()函数的示例代码

#include <variant>
#include <string>

int main()
{
    std::variant<int, float> v{12}, w;
    int i = std::get<int>(v);
    w = std::get<int>(v);
    w = std::get<0>(v); // same effect as the previous line

//  std::get<double>(v); // error: no double in [int, float]
//  std::get<3>(v);      // error: valid index values are 0 and 1

    try {
      std::get<float>(w); // w contains int, not float: will throw
    }
    catch (std::bad_variant_access&) {}
}
在 XCode 10 中,我的项目设置为 C++17,但我遇到了编译器错误:

调用不可用的函数'get': 在 macOS 10.14 中引入

'bad_variant_access' 不可用:在 macOS 10.14 中引入

这两种情况很奇怪:如果支持 std::variant ,则应该编译通过,关于 macOS 10.14 的提示也很奇怪,因为我正在使用该版本并且与支持的 C++ 方言无关(项目的部署目标是 10.14)。

这是我做错了什么还是 clang 的 bug?

2个回答

25

从 macOS 10.14 开始(以及相应的 iOS、tvOS 和 watchOS),所有可能引发 std::bad_variant_access 异常的 std::variant 功能都在标准头文件中标记为可用。这是因为虚拟的 std::bad_variant_access::what() 方法不是 inline 的,因此由操作系统提供的 libc++.dylib 中定义。

如果您想在较旧的操作系统上运行应用程序中使用 std::variant,只需使用 std::get_if。例如:

if (auto* p = std::get_if<int>(&w)) {
  // use *p
} else {
  // error handling
}
你还可以提前使用w.index()std::holds_alternative<int>(w)进行检查。 编辑: 另请参阅我在此处针对具有类似问题的std::visit的答案(不幸的是,解决方法不太方便)。

2
好的解释 - 现在我们知道为什么存在这个限制(以及解决方法)! - Mike Lischke
我们能否使用std::get_if模拟std::get的行为?前者相当冗长 :( - ch271828n
@ch271828n 你所说的“模拟”是什么意思?你可以将其分解成自己的get函数模板。但是它会抛出哪个异常? - Tobi
@Tobi,对我来说,只要像runtime_error这样抛出异常就足够了。但是我有点担心引用与指针的问题——我必须解引用指针并将其作为引用返回——这样安全吗?我的天真实现是否正确?-> https://gist.github.com/fzyzcjy/8633198b2cb03fe8585870d1a554d101 - ch271828n
对我来说看起来不错,@ch271828n。但通常情况下,您需要提供所有四个重载(类型/索引模板参数)x(const / non-const变量参数)。 - Tobi

5

事实证明,该项目设置为macOS 10.14,但实际的构建目标仍然是10.13。一旦我将其恢复为继承部署目标,测试代码就可以编译成功。

这是一个有趣的转折,因为XCode 10(因此LLVM 10.0)可以安装和用于在10.13上构建C++17应用程序。


3
苹果似乎是有意破坏系统以鼓励用户升级到 Mojave。官方的 LLVM (可通过 Homebrew 安装)则没有任何问题。 - Yongwei Wu
我猜这意味着您不能在10.13目标上使用std::variant。 - Mike Lischke
6
是的,如果代码旨在与默认编译器一起使用。由于我主要不是为了 Mac 开发,而是在 Mac 上开发,所以我可以自由地使用其他编译器。仍然非常遗憾的是,苹果公司很吝啬,并且只允许一个完全正常的非操作系统依赖性功能在最新的 macOS/iOS/... 版本上运行。 - Yongwei Wu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接