половина lvalue
замечательный вопрос на кворе:
почему бы гуглу не сделать свой IDE типа Visual Studio.
случайно посмотрел на ответы, они забавные.
но, как говорится, не тулзами едиными.
вчера в совершенно невинном вопросе про битовые поля я внезапно наткнулся на знакомого персонажа в колосящейся ржи стандарта.
тернарный оператор рваными зигзагами убегал за горизонт, но из узкой бездонной
расщелины на меня немигающе смотрели глаза Ангела С++, знакомые нам по будущим сериям.

действительно, возьмем совершенно обычный случай создания временных объектов.
“When initializing a const reference from a bit field, a temporary is created (its type is the type of the bit field), copy initialized with the value of the bit field, and the reference is bound to that temporary.” (8.5.3/5)
и оно совершенно очевидно, что иначе и быть не может, и я этим пользовался почти всегда.
и я спокойно перечитывал пропоузалы и лакомился новшествами в парсинге С++20:
int a;
struct foo {
int y1 : true ? 8 : a = 42;
int z : 1 || new int { 0 };
};
когда вдруг из lvalue битового поля на меня набросился тернарный оператор.
тернарный оператор оказался на высоте.
он на ровном месте моментом расширил мне чакру, и наглядно
продемонстрировал еще один случай, где люди считающие что
“у каждого выражения в С++ есть тип” скорее галлюционируют чем описывают
то что у них под ногами.
попутно обнаружил, что gcc поддерживает самые удивительные фичи языка.
авторы clang оказались большими озорниками и научили clang выдавать ошибки типа
“я страус, идите все в сад, я не буду даже пытаться это компилировать”
(LLVMbug 13809)
prog.cpp:4:2: error: cannot compile this conditional operator yet
f.w ? f.w : f.w;
это в ответ на простой как слеза ягненка годболт:
struct foo { int x : 2, y : 2, z : 2, w : 2; };
int main() {
foo f {};
f.w ? f.w : f.w;
}
и это ведь мы даже еще не перешли к подготовительной фазе типа “кто тут у нас lvalue”:
++(f.x ? f.y : f.z);
и к решающей фазе типа “ну давайте уже в 2017 будем С++17”:
(f.x ? f.y : f.z) = (f.x++) + 2;
заметьте, цитата стандарта выше – она про const T&, то есть например когда мы внезапно пишем втупую:
template<typename U>
const U& boo(const U& a, const U& b, const U& c) { return a ? b : c; }
// ...
boo(f.x, f.y, f.z); // насоздавали копий битовых полей и счастливы.
а вот подготовительные и решительные фазы –
они про тот самый реальный мимолетный битфилдный lvalue
которого нет но который как бы есть, и про возможность которого
понятное дело как обычно знает примерно три с половиной человека на планете.
знает, но не говорит.
gcc в этом смысле совершенно зубодробилен и работает на ура,
и действительно инкрементирует ровно то битовое поле что нужно:
tio.run
// ++(f.x ? f.y : f.z);
0 0 0 0
0 0 1 0
можем ведь!
хотя, возможно, лучше бы и не могли.
ну да ладно.
пора открывать поверпойнт и создавать будущее.
/ме вдохновенно устремил взор вдаль.