在C ++中,至少在GCC和Clang上,嵌入在容器(std :: vector)中的超对齐类型似乎被不同地对待,具体取决于该类型是超对齐结构还是超对齐枚举。对于struct版本,每个元素都对齐,而对于枚举,只有整个缓冲区具有指定的对齐方式。该行为是否由标准指定?如果是这样,哪一部分提到了?还是实现定义的,不应该依赖?
考虑以下:
#include<cstdint>
#include<iostream>
#include<vector>
struct alignas(16) byte_struct {std::uint8_t value;};
enum alignas(16) byte_enum : std::uint8_t {};
int main() {
{//with struct
std::vector<byte_struct> bytes;
bytes.push_back(byte_struct{1});
bytes.push_back(byte_struct{2});
bytes.push_back(byte_struct{3});
for(auto it = bytes.begin(); it!= bytes.end(); ++it) {
std::cout<<&*it<<std::endl;
}
}
{//with enum
std::vector<byte_enum> bytes;
bytes.push_back(byte_enum{1});
bytes.push_back(byte_enum{2});
bytes.push_back(byte_enum{3});
for(auto it = bytes.begin(); it!= bytes.end(); ++it) {
std::cout<<&*it<<std::endl;
}
}
}
Run Code Online (Sandbox Code Playgroud)
具有过度对齐的结构的版本将打印以下内容
0x10a9ec0 0x10a9ed0 0x10a9ee0
带有过度对齐的枚举的版本将打印以下内容
0x10a9e70 0x10a9e71 0x10a9e72
在向量存储区中,每个byte_struct都对齐到16个字节的边界,而byte_enum的对齐方式只适用于整个缓冲区,而不适用于每个单独的元素。
在GCC 9.1和Clang 8.0上,此行为相同,而MSVC 19.20遇到内部编译器错误。
编译器资源管理器的链接为:https : //godbolt.org/z/GUg2ft
考虑以下代码段(可在编译器epxlorer上获得):
template<typename T, typename... Args>
auto foo(Args&&... args) {}
template<typename... Args>
auto foo(Args&&... args) {}
int main() {
foo<char>('a');
}
Run Code Online (Sandbox Code Playgroud)
对于GCC而言,它可以完美编译,而对于Clang和MSVC而言,则均无法编译(编译器表示模棱两可的调用)
为什么Clang和MSVC无法如此看似明显的演绎?
编辑:GCC作为用户为我提供了预期的解决方案,是否有一种简单的方法来推动clang和msvc选择模板,而无需对原始代码进行太多更改?