dCu*_*lic 17 c++ xcode ios c++17
使用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;
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
main.cpp:27:5:调用不可用的函数'visit':在macOS 10.14中引入
但是,如果我将最小部署目标更改为macOS 10.14,则代码编译正常并且可以正常运行,即使我正在运行macOS 10.13.
由于std::visit是功能模板,并且不应该依赖于操作系统版本(我通过在较低版本的mac上运行代码而不是实际支持的证明),这应该被视为错误并报告给Apple还是这种预期的行为?
编译iOS时会出现同样的情况(iOS 12是最低限度的预期).
从标准头文件中的macOS 10.14(以及相应的iOS,tvOS和watchOS)开始,所有std::variant可能抛出的功能std::bad_variant_access都标记为可用。这是因为std::bad_variant_access::what()没有inline(因此libc++.dylib由OS提供)定义了虚拟方法。
有几种解决方法(所有技术上未定义的行为),根据我的个人喜好排序:
std::visit仅在变体参数之一为时抛出valueless_by_exception。研究实现可以为您提供使用以下变通办法的线索(假定vs是变量的参数包):
if (... && !vs.valueless_by_exception() ) {
std::__variant_detail::__visitation::__variant::__visit_value(visitor, vs...);
} else {
// error handling
}
Run Code Online (Sandbox Code Playgroud)
缺点:将来的libc ++版本可能会中断。界面难看。
优点:编译器在中断时可能会大吼大叫,并且可以轻松地采用变通办法。您可以针对丑陋的界面编写包装器。
添加_LIBCPP_DISABLE_AVAILABILITY到项目设置预处理器宏(GCC_PREPROCESSOR_DEFINITIONS)
缺点:这还将禁止其他可用性保护措施(shared_mutex,bad_optional_access等等)。
事实证明,它已经可以在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
Run Code Online (Sandbox Code Playgroud)
第一行取消约束_typeinfo for std::bad_variant_access。这意味着动态链接器(dyld)找不到指向what()引言中提到的方法的vtable 。
缺点:仅适用于某些操作系统版本,只有在启动时才能了解它是否起作用。
Pro:保持原始界面。
将以下行添加到项目源文件之一:
// Strongly undefined behaviour (violates one definition rule)
const char* std::bad_variant_access::what() const noexcept {
return "bad_variant_access";
}
Run Code Online (Sandbox Code Playgroud)
我已经针对10.10.0、10.12.6、10.13.0、10.14.1上的独立二进制文件对此进行了测试,即使在引发a std::bad_variant_access,被捕获std::exception const& ex并调用virtual的情况下,我的示例代码也可以正常工作ex.what()。
缺点:我的假设是,在使用RTTI或跨二进制边界的异常处理(例如,不同的共享库)时,此技巧将失效。但这只是一个假设,这就是为什么我最后采用此解决方法:我不知道它何时会破裂以及症状会是什么。
Pro:保持原始界面。可能会在所有OS版本上运行。
| 归档时间: |
|
| 查看次数: |
2749 次 |
| 最近记录: |