DoD*_*oDo 12 c++ libc++ c++17 std-variant
基本上,我们有这个代码片段:
#include <cstdint>
#include <variant>
enum class Enum1 : std::uint8_t { A, B };
enum class Enum2 : std::uint8_t { C, D };
using Var = std::variant< Enum1, Enum2 >;
using Var2 = std::variant< char >;
template< std::size_t s >
struct print_size;
void func() {
print_size< sizeof( Var ) >{};
print_size< sizeof( Var2 ) >{};
}
Run Code Online (Sandbox Code Playgroud)
如果我们使用GCC的libstdc ++(使用clang或GCC)编译它,我们会得到预期的编译错误:
error: implicit instantiation of undefined template 'print_size<2>'
Run Code Online (Sandbox Code Playgroud)
此外,与MSVC类似(如预期):
error C2027: use of undefined type 'print_size<2>'
Run Code Online (Sandbox Code Playgroud)
但是,当使用clang与libc ++时,我收到此错误:
error: implicit instantiation of undefined template 'print_size<8>'
Run Code Online (Sandbox Code Playgroud)
这表明sizeof( std::variant< char > ) == 8使用libc ++时.我已经确认在Linux上(参见上面的编译器浏览器链接),还有Android的NDK r18和Xcode 10(iOS和MacOS).
有没有理由让libc ++实现std::variant使用如此多的内存,或者这只是libc ++中的一个错误,应该向libc ++开发人员报告?
原因似乎是在libc ++的原始std::variant实现unsigned int中始终用于存储活动类型索引std::variant,而libstdc ++选择能够存储最大索引的最小无符号整数类型.
在当前的libc ++中,此优化也可用,但默认情况下似乎没有启用.宏使优化(_LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION)时,才设置,如果_LIBCPP_ABI_VERSION >= 2或_LIBCPP_ABI_UNSTABLE定义.
我想,因为原始实现没有进行这种优化,并且std::variant由于数据布局的改变而破坏了两个方向的兼容性,所以默认情况下它没有启用以保持与旧版本的二进制兼容性.可以通过设置提到的ABI版本宏来启用较新的ABI,但当然所有库也需要使用这个新的ABI版本进行编译.
请参阅https://reviews.llvm.org/D40210
| 归档时间: |
|
| 查看次数: |
425 次 |
| 最近记录: |