Ich habe einen Code, der mehr oder weniger so ist:
#include <bitset>
enum Flags { A = 1, B = 2, C = 3, D = 5,
E = 8, F = 13, G = 21, H,
I, J, K, L, M, N, O };
void apply_known_mask(std::bitset<64> &bits) {
const Flags important_bits[] = { B, D, E, H, K, M, L, O };
std::remove_reference<decltype(bits)>::type mask{};
for (const auto& bit : important_bits) {
mask.set(bit);
}
bits &= mask;
}
Clang> = 3.6 macht das and
Schlaue und kompiliert dies zu einer einzigen Anweisung (die dann überall sonst eingefügt wird):
apply_known_mask(std::bitset<64ul>&): # @apply_known_mask(std::bitset<64ul>&)
and qword ptr [rdi], 775946532
ret
Aber jede Version von GCC, die ich versucht habe, kompiliert dies zu einem enormen Durcheinander, das Fehlerbehandlung beinhaltet, die statisch DCE-fähig sein sollte. In anderem Code wird sogar das important_bits
Äquivalent als Daten in Übereinstimmung mit dem Code platziert!
.LC0:
.string "bitset::set"
.LC1:
.string "%s: __position (which is %zu) >= _Nb (which is %zu)"
apply_known_mask(std::bitset<64ul>&):
sub rsp, 40
xor esi, esi
mov ecx, 2
movabs rax, 21474836482
mov QWORD PTR [rsp], rax
mov r8d, 1
movabs rax, 94489280520
mov QWORD PTR [rsp+8], rax
movabs rax, 115964117017
mov QWORD PTR [rsp+16], rax
movabs rax, 124554051610
mov QWORD PTR [rsp+24], rax
mov rax, rsp
jmp .L2
.L3:
mov edx, DWORD PTR [rax]
mov rcx, rdx
cmp edx, 63
ja .L7
.L2:
mov rdx, r8
add rax, 4
sal rdx, cl
lea rcx, [rsp+32]
or rsi, rdx
cmp rax, rcx
jne .L3
and QWORD PTR [rdi], rsi
add rsp, 40
ret
.L7:
mov ecx, 64
mov esi, OFFSET FLAT:.LC0
mov edi, OFFSET FLAT:.LC1
xor eax, eax
call std::__throw_out_of_range_fmt(char const*, ...)
Wie soll ich diesen Code schreiben, damit beide Compiler das Richtige tun können? Wenn dies nicht der Fall ist, wie soll ich das schreiben, damit es klar, schnell und wartbar bleibt?
(1ULL << B) | ... | (1ULL << O)
(1ULL << Constant)
| pro Zeile und richten Sie die konstanten Namen auf den verschiedenen Zeilen aus, was für die Augen einfacher wäre.
int
Ergebnis der Bitverschiebung hier ist ein Ergebnis der Bitoperation, die int
möglicherweise long long
vom Wert abhängt und formal enum
ist nicht gleichbedeutend mit einer int
Konstanten. Clang fordert "als ob", gcc bleibt pedantisch
B | D | E | ... | O
?