gpt4 book ai didi

c++ - Xcode 10 调用不可用的函数 std::visit

转载 作者:IT老高 更新时间:2023-10-28 22:20:34 31 4
gpt4 key购买 nike

使用 Xcode 10 GM 编译以下程序时:

#include <iostream>
#include <string>
#include <variant>

void hello(int) {
std::cout << "hello, int" << std::endl;
}

void hello(std::string const & msg) {
std::cout << "hello, " << msg << std::endl;
}

int main(int argc, const char * argv[]) {
// insert code here...
std::variant< int, std::string > var;

std::visit
(
[]( auto parameter )
{
hello( parameter );
},
var
);

return 0;
}

我收到以下错误:

main.cpp:27:5: Call to unavailable function 'visit': introduced in macOS 10.14

但是,如果我将最小部署目标更改为 macOS 10.14,即使我运行的是 macOS 10.13,代码也可以正常编译并且可以正常工作。

由于 std::visit 是函数模板,并且不应该依赖于操作系统版本(我通过在低于实际支持的 mac 版本上运行代码证明了这一点),这应该被视为错误并报告给 Apple 还是这是预期的行为?

在为 iOS 编译时也会发生同样的情况(至少需要 iOS 12)。

最佳答案

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

有几种解决方法(技术上都是未定义的行为),按我的个人喜好排序:

1) 参与实现

std::visit 仅在变体参数之一是 valueless_by_exception 时抛出。查看实现为您提供了使用以下解决方法的线索(假设 vs 是变体的参数包):

if (... && !vs.valueless_by_exception() ) {
std::__variant_detail::__visitation::__variant::__visit_value(visitor, vs...);
} else {
// error handling
}

缺点:可能会与 future 的 libc++ 版本中断。丑陋的界面。

专业人士:编译器可能会在它崩溃时对你大喊大叫,并且可以轻松调整解决方法。您可以针对丑陋的界面编写一个包装器。

2) 抑制可用性编译器错误...

_LIBCPP_DISABLE_AVAILABILITY 添加到项目设置 Preprocessor Macros (GCC_PREPROCESSOR_DEFINITIONS)

缺点:这也会抑制其他可用性保护(shared_mutexbad_optional_access 等)。

2a) ... 并使用它

事实证明它已经在 High Sierra 中工作,而不仅仅是 Mojave(我已经测试到 10.13.0)。

在 10.12.6 及以下版本中,您会收到运行时错误:

dyld: Symbol not found: __ZTISt18bad_variant_access
Referenced from: [...]/VariantAccess
Expected in: /usr/lib/libc++.1.dylib
in [...]/VariantAccess
Abort trap: 6

第一行解构为 _typeinfo for std::bad_variant_access。这意味着动态链接器(dyld)找不到指向引言中提到的what()方法的vtable。

缺点:仅适用于某些操作系统版本,如果它不起作用,您只有在启动时才知道。

专业版: 保持原始界面。

2b) ...并提供您自己的异常实现

在您的项目源文件之一中添加以下行:

// Strongly undefined behaviour (violates one definition rule)
const char* std::bad_variant_access::what() const noexcept {
return "bad_variant_access";
}

我已经针对 10.10.0、10.12.6、10.13.0、10.14.1 上的独立二进制文件对此进行了测试,即使导致 std::bad_variant_access 为抛出,由 std::exception const& ex 捕获,并调用虚拟 ex.what()

缺点:我的假设是,当使用 RTTI 或跨二进制边界(例如不同的共享对象库)进行异常处理时,这个技巧会失效。但这只是一个假设,这就是我把这个解决方法放在最后的原因:我不知道它什么时候会破裂以及会出现什么症状。

专业版: 保持原始界面。可能适用于所有操作系统版本。

关于c++ - Xcode 10 调用不可用的函数 std::visit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52310835/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com