[C++] Где почитать про объявления классов внутри функций?

bleyman

Увидел в статье про C++0x упоминание о том, что классы можно объявлять внутри функций даже в стандартных плюсах. Проверил и действительно.
 
#include <search.h>

const int zzz(int i)
{
class Comparer
{
public:
static int Compare(const void * a, const void * b)
{
return *(int*)a - *(int*)b;
}
};

int arr[] = {3, 2, 1};

qsort(arr, sizeof(int 3, Comparer::Compare);

return arr[i];
}


int main
{
return zzz(2);
}

А вопрос, собственно, такой: где про это можно прочитать? У Страуструба что-то не нашёл. Может, это такое секретное знание?

vasena

iso/iec 14882 9.8 Local class definitions

bleyman

Прикольно, спасибо.

zya369

Сообщение удалил

smit1

class Comparer
{
public:
static int Compare(const void * a, const void * b)
{
return *(int*)a - *(int*)b;
}
};

int arr[] = {3, 2, 1};

qsort(arr, sizeof(int 3, Comparer::Compare);

Очень странный пример. На С++ такой код никто не пишет. И вообще, в С++ вложенные классы для чего либо содержательного использовать почти невозможно - например, они не могут быть параметрами шаблона (т.е. STL с ними никак не сочетается).

Dasar

И вообще, в С++ вложенные классы для чего либо содержательного использовать почти невозможно
а какая вообще есть польза от декларации класса внутри функции?
и с какой целью это было сделано? древнее наследие C?

evgen5555

У Александреску в книжке есть по этому поводу немного.

Dasar

передавать своими словами можешь что там было?
ps
если честно, то лень куда-то лезть ради удовлетворения небольшого любопытства :)

bleyman

Да, странный, конечно.
Там ещё и функция возвращает const int — я случайно обнаружил, что и это возможно, причём до сих пор не понимаю, нафига это нужно, если она и так возвращает rvalue.
И не работает она, кстати, потому что я идиот и перепутал длину и страйд! =)

evgen5555

Да я сейчас и сам не вспомню, а руку за книгой тянуть ломает.

smit1

>qsort(arr, sizeof(int 3, Comparer::Compare);
Тут вообще-то тупо баг, потому что у кусорта второй параметр - это кол-во элементов, а третий - размер элемента. Это типичнейший пример ошибки, которую невозможно было бы сделать, пользуясь нормальным С++ (т.е. std::sort ).
Ещё один из самых популярных источников безблагодатности - это void*, которым qsort тоже болен.

stat7984215

Там ещё и функция возвращает const int — я случайно обнаружил, что и это возможно, причём до сих пор не понимаю, нафига это нужно, если она и так возвращает rvalue.
Это иногда спасает от глупых от глупых ошибок наподобие

if ( zzz(1) = 2 )
{/*...*/}

Для функции это особо не нужно, но может быть полезно для всяких операторов:

struct A
{
//...
int operator[](size_t Index) {/*...*/}
};

voif f
{
A a;
a[1] = 2;
}

Особенно просто на такую ошибку нарваться в шаблонном коде.
Конечно, умный компилятор выдаст предупреждение про присваивание временной переменной, но, имхо, лучше подстраховаться.

erotic

имхо, лучше подстраховаться
Имхо, лучше положиться на предупреждения компилятора :)
Пробовал писать функции, которые возвращают const int, const double и прочие константны типы, но потом понял, что выглядит по-уродски.
P.S. Мое имхо, не бейте :)
P.P.S. Некоторые для защиты от такого пишут if (2 == zzz(1 что, конечно, не спасет от опечатки if (zzz(1) = zzz(2 если компилятор не поможет.
P.P.P.S. gcc на код if ( zzz(1) = 2 ) вообще ошибку выдает и без const.

Maurog

а какая вообще есть польза от декларации класса внутри функции?
древнее наследие C?

:shocked:

Dasar

например раньше было можно структуру внутри функции определять, теперь - класс.
зачем так тупить? :confused:

erotic

зачем так тупить?
Ну, может быть это в целях локализации использования? Надо тебе, например, объявить функтор, который ты используешь один раз в этой функции и забудешь. Если не объявлять его внутри функции, это надо делать где-то еще, например, в анонимном-неймспейсе прямо перед функцией, что не лишено недостатков, т.к. больше писать.

freezer

так написали же, что в шаблонах локальные классы использовать нельзя

slonishka

P.P.S. Некоторые для защиты от такого пишут if (2 == zzz(1
да, я уже давно на автомате так пишу.

vasena

Писать if (2 == z) это ухудшать читаемость кода.
Например, MS компилятор с опцией /w4 выдаст ворнинг, если напишешь так if (z=2) .
а if( z = 2 ) - просто нельзя писать по стандарту.

slonishka

читаемость кода ухудшается, если на александреску много дрочить.
такие выражения никого не смущают, проверено. =)
а if( z = 2 ) - просто нельзя писать по стандарту.
что за стандарт?
int main
{
int i;
++i = 1;

return 0;
}

на твоем MS-компиляторе скомпилится без проблем.

erotic

так написали же, что в шаблонах локальные классы использовать нельзя
Точно, забыл уже. Сам никогда не пользовался такими локальными классами.

smit1

>P.P.P.S. gcc на код if ( zzz(1) = 2 ) вообще ошибку выдает и без const.
Ну так и должно быть, возвращаемое функцией значение - это rvalue (если это не ссылка). Кстати, твой любимый gcc в этом аспекте не идеален, например, вот такой не соответствующий стандарту код он схавает:
struct S
{
int m;
};

S get_struct
{
S s;
s.m = 1;
return s;
}

int test(int, char**)
{
get_struct.m = 2;
}

erotic

Так тут у тебя ссылка возвращается, а z - значение. Что если ты напишешь i++ = 1?

smit1

>что за стандарт?
Йазыка С++.

smit1

>на твоем MS-компиляторе скомпилится без проблем.
А на каком не скомпилицо?

erotic

вот такой не соответствующий стандарту код он схавает:
А что тут не соответствует стандарту?

slonishka

там про значение не было ничо, оторванная от контекста фраза про то,
что по стандарту нельзя писать "z = 1" — не правильная.

slonishka

icpc и sunСС тоже схавали.
правда icpc выдал ремарку, что экстернал функция не объявлена.

slonishka

ты имел в виду, что к rvalue нельзя operator. применять и использовать, как lvalue чтоли?
ну фиг знает, вот вы знатоки-то адские...

smit1

>ты имел в виду, что к rvalue нельзя operator. применять чтоли?
>ну фиг знает, вот вы знатоки-то адские...
Ну методы вроде как можно вызывать. А вот выражение типа rvalue.chlen_ вроде как должно быть rvalue, если член - не ссылка :-) Хотя стандарт тут несколько невнятен, если мне умные люди объяснят, что я неправ и ваще мудак, охотно признаю :-) Кстати, студия тоже это хавает. Не хавает только комю :-)

smit1

>Увидел в статье про C++0x упоминание о том, что классы можно объявлять внутри функций даже в стандартных плюсах.
Кстате, а что именно читал-то, поделись ссылкой.

bleyman

http://en.wikipedia.org/wiki/C%2B%2B0x
Какой-то вообще звиздец они готовят, по-моему. Решают проблемы существующих фишек путём добавления новых.
То есть мне кажется, что у них не всё в порядке с головой, на самом деле. Вот например, добавили type traits в темплейты и пишут
Through type traits, defined in header <type_transform>, it’s also possible to create type transformation operations (static_cast and const_cast are insufficient inside a template).
This type of programming produces elegant and concise code; however the weak point of these techniques is the debugging: uncomfortable during compilation and very difficult during program execution.
Человек, называющий что угодно, относящееся к плюсовому темплейтному "метапрограммированию", ОСОБЕННО их конкретный пример для traits, словами elegant and concise, либо не видел ни одного языка кроме плюсов (и тогда не очень понятно, сфига ж его пустили их дизайнить либо полностью убил в себе способность к критическому мышлению. Это говно, говно, говно, такой код нужно выжигать огнём, language facilities позволяющие писать такой код нужно выжигать огнём, вот не зря K&R _специально_ потребовали запретить повторное раскрытие макросов и обработку #define внутри макроса (его туда можно впихнуть отбэкслешив ньюлайн чтобы ни у кого даже мысли не возникало "метапрограммировать" на макросах что-нибудь тьюринг-полное, а у тех, у кого возникало (осталась loophole с #include время компиляции простейших вещей было таким, что получающиеся штуковинки не воспринимались иначе как эзотерические развлекушечки.

slonishka

Какой-то вообще звиздец они готовят, по-моему. Решают проблемы существующих фишек путём добавления новых. То есть мне кажется, что у них не всё в порядке с головой, на самом деле. Вот например, добавили type traits в темплейты и пишутThrough type traits, defined in header <type_transform>, it’s also possible to create type transformation operations (static_cast and const_cast are insufficient inside a template).This type of programming produces elegant and concise code; however the weak point of these techniques is the debugging: uncomfortable during compilation and very difficult during program execution.
да уж, круто.
Оставить комментарий
Имя или ник:
Комментарий: