Здравствуйте, B0FEE664, Вы писали:
R>>Так вот это оно самое. BFE>Да неужели?
Да точно-точно.
BFE>А писать ++it вместо it++ — тоже преждевременная оптимизация?
Нет. Но писать it++ вместо ++it — это преждевременная пессимизация. Зачем писать более сложное выражение, когда можно написать более простое при прочих равных условиях? Подробнее здесь: https://doc.lagout.org/programmation/C/CPP101.pdf, рекомендация №9: "Don't pessimize prematurely".
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, andrey.desman, Вы писали:
AD>Ибо потому что через тупл надо, потому что тут присваивание, а значит {} описывает initializer_list вместо конструктора. Были бы разные типу у it и i2, то даже до этого не дошел бы.
А откуда тут initializer_list ? Зачем он тут?
struct A
{
int n;
char* s;
};
A a = {1, nullptr};
А если убрать присваивание, то почему не работает?
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, andrey.desman, Вы писали:
AD>>Ибо потому что через тупл надо, потому что тут присваивание, а значит {} описывает initializer_list вместо конструктора. Были бы разные типу у it и i2, то даже до этого не дошел бы. BFE>А откуда тут initializer_list ? Зачем он тут?
Потому что так придумали.
A std::initializer_list object is automatically constructed when: a braced-init-list is bound to auto, including in a ranged for loop
BFE>
BFE>struct A
BFE>{
BFE> int n;
BFE> char* s;
BFE>};
BFE>A a = {1, nullptr};
BFE>
BFE>
Это copy-list-initialization и там не initializer_list, а braced-init-list.
BFE>А если убрать присваивание, то почему не работает? BFE>
int i;
char c;
auto list = { i, c }; // initalizer_list, failauto [a, b] = list; // fail даже если list состояится как initializer_list, потому что он не массив и не тупл, значит привязка пойдет по членам класса.
Здравствуйте, andrey.desman, Вы писали:
BFE>>А откуда тут initializer_list ? Зачем он тут? AD>Потому что так придумали.
Предположим, что так, хотя я сомневаюсь.
AD>A std::initializer_list object is automatically constructed when: a braced-init-list is bound to auto, including in a ranged for loop
А это наш случай? У нас structured binding, а не bound to auto. Разве это одно и тоже?
AD>Это copy-list-initialization и там не initializer_list, а braced-init-list.
Что говорит нам о том, что типы не обязаны быть одинаковыми. initializer_list не нужен.
BFE>>А если убрать присваивание, то почему не работает? BFE>>
BFE>>auto [a, b]{i1, i2};
BFE>>
AD>С чего бы ей работать?
С того, что ничему не противоречит. AD>Смотри как объявляется structured binding https://en.cppreference.com/w/cpp/language/structured_binding.
Я смотрел.
AD>В expression вообще запятой быть не положено, а когда ты = убираешь, то оно спотыкается уже на этом.
Не должно быть оператора запятая. Где у меня операторы?
AD>Твой изначальный код — это примерно следующее: AD>auto list = { i, c }; // initalizer_list, fail
initalizer_list отсутствует в structured binding описании.
Предположим, что всё так, как вы пишите. Тогда получается, что это практически безполезная фича языка. Жаль, могла получиться красивая конструкция.
Здравствуйте, B0FEE664, Вы писали:
AD>>A std::initializer_list object is automatically constructed when: a braced-init-list is bound to auto, including in a ranged for loop BFE>А это наш случай? У нас structured binding, а не bound to auto. Разве это одно и тоже?
Наш. См. ниже.
AD>>Это copy-list-initialization и там не initializer_list, а braced-init-list. BFE>Что говорит нам о том, что типы не обязаны быть одинаковыми. initializer_list не нужен.
Тут не обязаны, тут не нужен.
BFE>С того, что ничему не противоречит.
Противоречит описанию.
AD>>В expression вообще запятой быть не положено, а когда ты = убираешь, то оно спотыкается уже на этом. BFE>Не должно быть оператора запятая. Где у меня операторы?
У выражения не может быть не оператора ",", поэтому там именно оператор.
AD>>Твой изначальный код — это примерно следующее: AD>>auto list = { i, c }; // initalizer_list, fail BFE>initalizer_list отсутствует в structured binding описании.
Ему там и не надо быть. Если expression не массив, то.
Otherwise e is defined as if by using its name instead of [ identifier-list ] in the declaration.
Т.е.
auto [a, b] = {1,2,3};
// =>auto e = {1,2,3}; // initializer_list
...
BFE>Предположим, что всё так, как вы пишите. Тогда получается, что это практически безполезная фича языка. Жаль, могла получиться красивая конструкция.
Почему бесполезная? Потому что присваивания параллельными пачками нельзя делать, не написав std::tuple?
Здравствуйте, _NN_, Вы писали:
_NN>Насколько я понимаю в теории можно специализировать std::get для initalizer_list и тогда код соберётся
Там сказано, что можно просто написать:
Здравствуйте, andrey.desman, Вы писали:
AD>Почему бесполезная? Потому что присваивания параллельными пачками нельзя делать, не написав std::tuple?
Почему С++ не называется "с = с + 1"?
Вот и тут так же.
_NN>Или хочется новый синтаксис ввести в язык ?
Так в том-то и дело, что синтаксис новый добавили, но с несколько неожиданным поведением.
_NN>Можно попытаться через stdcpp.ru
Сначало можно тут обсудить.
Например, можно было бы ввести новый оператор, который никакой роли сам в языке по себе не играет, но который можно перегрузить для любого, не только пользовательского типа.
float operator =>(MyVariant from, float to)
{
if ( ! from.IsFloat() )
throw std::bad_cast();
to = from.get<float>();
return to;
}
int operator =>(float from, int to)
{
if ( static_cast<float>(static_cast<int>(from)) != from )
throw std::bad_cast();
to = static_cast<int>(from);
return to;
}
Использование:
MyVariant my(1.2f);
float my => f;
int f => n;
float x = 1.f;
o => x;
std::size_t const size = std::size( data );
for( auto [ i, v ] = enumerate( data ) ) {
if( i == 0 ) {} // первый элемент (или единственный, если size( data ) == 1)else if( i + 1 == size ) {} // последний элементelse {} // между первым и последним
}
Для вывода с запятыми:
for( auto [ i, v ] : enumerate( data ) ) {
if( i != 0 ) {
std::cout << ", ";
}
std::cout << v;
}