интересуюсь, почему язык поддерживает конструкции вида:
if (const Foo *pFoo = getFoo()) {
//работаем далее с pFoo
}
//здесь уже pFoo нет
но не поддерживает
if ((const Foo *pFoo = getFoo()) == VALUE) {
//работаем далее с pFoo
}
//здесь уже pFoo нет
на подобное натыкаюсь зачастую, и приходится вместо этого писать:
const Foo *pFoo = getFoo();
if (pFoo){
//работает далее с pFoo
}
//здесь уже pFoo нет
но немного не нравится, т.к. по логике сама переменная pFoo нам нужна только в теле блока if, а получается, что в моем последнем примере она будет доступна далее _после_ тела if. или я много хочу?
спасибо за комменты.
Здравствуйте, _nn_, Вы писали:
__>Здравствуйте, varnie, Вы писали:
__>На мой взгляд нужно просто избавляться от такого кода. __>Лучше уже писать: __>
__>Foo& f = getFoo();
__>// работаем с f
__>
__>А если getFoo проваливается выскакивает исключение
у меня подразумевается общий пример, взятие указателя и дальнейшие действия при условии что он валиден — не единственный предмет моего вопроса.
например, нам надо узнать есть ли в массиве число удовлетворяющее нашим условиям, и если оное имеется -- вывести его в консоль. т.е. если его нету, то мы не будем выбрасывать исключение, т.к. для нашей задачи это приемлемо, это некритично.
вот про задачи с подобным контекстом я и спрашиваю. хотел бы ограничить область видимости переменной, используемой для 5-6 строчек кода, используемой в определенной подзадаче. вот и все.
или это я такой педантичный и дотошный.
Здравствуйте, varnie, Вы писали:
V>Здравствуйте, _nn_, Вы писали:
__>>Здравствуйте, varnie, Вы писали:
__>>На мой взгляд нужно просто избавляться от такого кода. __>>Лучше уже писать: __>>
__>>Foo& f = getFoo();
__>>// работаем с f
__>>
__>>А если getFoo проваливается выскакивает исключение
V>у меня подразумевается общий пример, взятие указателя и дальнейшие действия при условии что он валиден — не единственный предмет моего вопроса.
А зачем указатель ?
V>например, нам надо узнать есть ли в массиве число удовлетворяющее нашим условиям, и если оное имеется -- вывести его в консоль. т.е. если его нету, то мы не будем выбрасывать исключение, т.к. для нашей задачи это приемлемо, это некритично.
V>вот про задачи с подобным контекстом я и спрашиваю. хотел бы ограничить область видимости переменной, используемой для 5-6 строчек кода, используемой в определенной подзадаче. вот и все. V>или это я такой педантичный и дотошный.
Здравствуйте, varnie, Вы писали:
V>здравствуйте все.
V>интересуюсь, почему язык поддерживает конструкции вида: V>
V> if (const Foo *pFoo = getFoo()) {
V> //работаем далее с pFoo
V> }
V> //здесь уже pFoo нет
V>
V>но не поддерживает V>
V> if ((const Foo *pFoo = getFoo()) == VALUE) {
V> //работаем далее с pFoo
V> }
V> //здесь уже pFoo нет
V>
V>на подобное натыкаюсь зачастую, и приходится вместо этого писать: V>
V> const Foo *pFoo = getFoo();
V> if (pFoo){
V> //работает далее с pFoo
V> }
V> //здесь уже pFoo нет
V>
V>но немного не нравится, т.к. по логике сама переменная pFoo нам нужна только в теле блока if, а получается, что в моем последнем примере она будет доступна далее _после_ тела if. или я много хочу? V>спасибо за комменты.
VC компилятор думает что открывающая скобка перед типом есть начало записи преобразования типа, вроде
(some_type)x, поскольку понять что там есть на самом деле, он может только после глубокого просмотра вперед..например если выражение сложное
(int x=f()+ff()+fff()... )
то разумеется он далеко вперед не смотрит и ругается.
если С++ делали не идиоты, такая конструкция вообще должна быть запрещена —
открывающая скобка перед именем типа, если это не преобразование.
V> const Foo *pFoo = getFoo();
V> if (pFoo){
V> //работает далее с pFoo
V> }
V> //здесь уже pFoo нет
V>
V>но немного не нравится, т.к. по логике сама переменная pFoo нам нужна только в теле блока if, а получается, что в моем последнем примере она будет доступна далее _после_ тела if. или я много хочу? V>спасибо за комменты.
Можно для этого использовать другой блок.
{ // Открыли блок в котором будет жить pFoo const Foo *pFoo = getFoo();
if (pFoo == VALUE)
{
}
// здесь pFoo есть
} // а здесь уже рыбы нет.
Насколько я помню, такой синтаксис (объявление переменной прямо в if) в основном предназначается для даункастинга:
if (const *pBar = dynamic_cast<const Bar*>(getFoo()))
{
}
else if (const *pFoo = dynamic_cast<const Foo*>(getFoo()))
{
}
else if (...
Возможно, попытки применить этот синтаксис как-то по другому сродни попытке использовать for не для инициализации-проверки-инкремента итератора.
Здравствуйте, Alexander G, Вы писали:
AG>Возможно, попытки применить этот синтаксис как-то по другому сродни попытке использовать for не для инициализации-проверки-инкремента итератора.
Он предназначен для проверки указателей, которые откуда-то возвращаются и с которыми дальше можно работать только если они ненулевые, а это — один из самых распространенных сценариев, и даункастинг тут — о малое.
Здравствуйте, varnie, Вы писали:
V>но немного не нравится, т.к. по логике сама переменная pFoo нам нужна только в теле блока if, а получается, что в моем последнем примере она будет доступна далее _после_ тела if. или я много хочу?
Многого. Подумай не тему времени жизни pFoo с учетом того, где и как он объявлен, и где и как ты его объявляешь.
Плюс твой пример можно обобщить: ведь необязательно мы хотим сравнивать, возможно, мы захотим позвать метод и проверить то, что он вернет:
if (Object& o = get_object(); o.is_valid() )
{
// работаем с o
}
или родить несколько объектов и проверять сложные условия:
if (Object1& o1 = get_object1(); Object2* o2 = get_object2(); o1.field == o2->field )
{
// работаем с o1, o2
}
ну а отсюда и до полноценной программы внутри if недалеко
Хотя, конечно, можно было бы изменить синтаксис как-то так:
if ( declaration-list_opt; expression_list_opt ) statement;
c соответсвующим временем жизни всех объявленных переменных.
но сообразил, что здесь это из пушки по воробьям. Поскольку проверка предиката выполняется ровно один раз, то проще хранить не сам предикат, а его результат.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[2]: наверно я многого хочу: поддержка конструкций
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rg45, Вы писали:
R>Просьба в серьез не принимать:
Анологично R>
R>for (const Foo* pFoo = getFoo(); pFoo == VALUE; )
R>{
R> //работаем далее с pFoobreak;
R>}
R>//здесь уже pFoo нет
R>
R>
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Roman Odaisky пишет: > Чего на самом деле не хватает, так это using, как в C#: > > using(X x = getX()) > if(i_like(x) && x.is_very_nice()) > { > . . . > } > > > В C++ это можно сделать только через for: > http://www.rsdn.ru/forum/message/2397489.1.aspx