LINUX.ORG.RU

Планы по выпуску GTK+ версии 3

 


1

0

В списке рассылки gtk-devel-list обсуждаются планы выпуска GTK+ версии 3. Основные подготовительные действия, которые необходимо предпринять в текущей ветке:

  • Спрятать все открытые поля структур с помощью макроса GSEAL(). В случае необходимости предоставить новые методы доступа к этим полям. Также должны быть скрыты поля-указатели "priv" на структуры, содержащие закрытые данные. Эти действия уже практически полностью проведены в репозитории git://git.imendio.com/projects/gtk+.git
  • Реализовать закрытые члены класса, что включает изменения в коде GType.
  • Объявить как deprecated публичные данные класса с помощью макроса GSEAL().
  • Поскольку не останется простого способа для доступа к полям класса, а использование g_object_[sg]et() утомительно, необходимо ввести новые методы доступа, вроде g_object_get_int(), *double(), *string() и т.д.
  • Существует множество макросов, таких как GTK_WIDGET_GET_FLAGS(), которые всегда были причиной многочисленных проблем (см. bug #69872). Необходимо реализовать нормальные методы доступа (в виде функций) и избавиться от этих макросов.
  • GtkStyle, без сомнений, самый сложный тип, нуждающийся в скрытии публичных полей, и до релиза должно быть проведено множество исследований.
  • Избавиться от всего кода, объявленного deprecated в 2.x. Это подразумевает все соответствующие виджеты и функции.
  • Удалить все поля структур из публичного API. Есть два способа достичь этого:
    a) переместить все структуры в закрытые заголовки;
    b) переместить структуры в C-файл реализации, но тогда всей библиотеке придётся использовать соответствующие методы доступа.
    Эти варианты ещё обсуждаются.
  • Отключить deprecated-код по умолчанию во флагах компиляции.
Таким образом, версия 3.0 будет готова к релизу. Все приложения, которые собираются для ветки 2.x с макросом GSEAL() и не используют deprecated-кода, будут без проблем собираться для ветки 3.x. Наверное, таким образом разработчики пытаются избежать кошмара миграции, который можно видеть на примере библиотеки Qt.

>>> Подробности

★★★★

Проверено: JB ()
Ответ на: комментарий от Absurd

> Либо платонический любитель плюсов типа tailgunner'а которому на Сях видимо скучно, и ищет приключений на свою голову.

Я начал программиовать на Си++ году в 90-м, и перестал не по свое воле в 2000-м. Планирую вернуться ;)

tailgunner ★★★★★
()
Ответ на: комментарий от gaa

> И это быстрее(во время исполнения), чем прописать для каждого поля присваивание

При чем тут быстрее? Это концептуально неправильно - позволять в ОО языке такие неявности. Это замусоривание внимания программиста всякой чухней.

> Надо всего лишь привыкнуть.

Звучит как фраза в несуществующем анекдоте про секс в Запорожце. Человек ко всему привыкает, да.

svu ★★★★★
()
Ответ на: комментарий от gaa

> Если рассматривать идеально сферический ОО язык безо всяких претензий на допущение оптимизированных реализаций операций, то да.

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

С++ - это не процедурный язык. Не модульный. Не ОО язык. Это компромиссный язык. Все, что в нем есть - это компромиссы.

svu ★★★★★
()
Ответ на: комментарий от svu

> Это концептуально неправильно - позволять в ОО языке такие неявности. Это замусоривание внимания программиста всякой чухней.

Прототипы обычно пишут на более других языках. А уж в реализации только о такой, как Вы выразились, "чухне" и надо думать.

> С++ - это не процедурный язык. Не модульный. Не ОО язык. Это компромиссный язык. Все, что в нем есть - это компромиссы.

Да, это компромиссный язык. Компромисс между скоростью и неуловимой оо-трушностью.

gaa ★★
()
Ответ на: комментарий от gaa

> Прототипы обычно пишут на более других языках

Очень немногие проекты позволяют себе такое двуязычие. И если уж при реализации ТАК важна производительность - небольшие куски кода лучше сделать на С, меньше геморрою с байндингами будет.

> Компромисс между скоростью и неуловимой оо-трушностью.

Типическая гонка за двумя зайцами.

svu ★★★★★
()
Ответ на: комментарий от svu

>> Прототипы обычно пишут на более других языках

> Очень немногие проекты позволяют себе такое двуязычие.

Зачем двуязычие? Написал прототип на КрутомПрототипномЯзыке, затем переписал на КрутомЯзыкеРеализаций. Остаётся только один язык.

> И если уж при реализации ТАК важна производительность - небольшие куски кода лучше сделать на С, меньше геморрою с байндингами будет.

Изя, и эти люди не любят Tcl! (c) :)

>> Компромисс между скоростью и неуловимой оо-трушностью.

> Типическая гонка за двумя зайцами.

Плюсам она удалась лучше других. Вот покажите мне язык с производительностью приближенной к сишной и возможностью легко оперировать ненавистными Absurd-у листами, мапами и алгоритмами с ними?

gaa ★★
()
Ответ на: комментарий от gaa

> Зачем двуязычие? Написал прототип на КрутомПрототипномЯзыке, затем переписал на КрутомЯзыкеРеализаций. Остаётся только один язык.

Двуязычие в данном случае - в процессе, а не в результате.

> Плюсам она удалась лучше других.

Ага. Этих двух зайцев они видели с минимального расстояния. Поймать-не поймали, так хоть полюбовались.

> Вот покажите мне язык с производительностью приближенной к сишной и возможностью легко оперировать ненавистными Absurd-у листами, мапами и алгоритмами с ними?

Постановка _взаимоисключающих_ целей - верный путь к провалу.

svu ★★★★★
()
Ответ на: комментарий от gaa

>>> Компромисс между скоростью и неуловимой оо-трушностью.

>> Типическая гонка за двумя зайцами.

> Плюсам она удалась лучше других. Вот покажите мне язык с производительностью приближенной к сишной и возможностью легко оперировать ненавистными Absurd-у листами, мапами и алгоритмами с ними?

Насколько приближенная производительность устроит? 8) Вообще-то Ocaml (и, наверное, другие языки ML-семейства) выдает 50% производительности Си. Другое дело, что они требуют переучивания, и их просто не было в середине 80-х.

tailgunner ★★★★★
()
Ответ на: комментарий от svu

>> Вот покажите мне язык с производительностью приближенной к сишной и возможностью легко оперировать ненавистными Absurd-у листами, мапами и алгоритмами с ними?

> Постановка _взаимоисключающих_ целей - верный путь к провалу.

Вот интеловцы-то не знают. Клепают, бедные, библиотеки для высокопроизводительных вычислений на плюсах, о провале не ведают...

gaa ★★
()
Ответ на: комментарий от tailgunner

> Насколько приближенная производительность устроит? 8)

Чем ближе, тем лучше :)

> Вообще-то Ocaml (и, наверное, другие языки ML-семейства) выдает 50% производительности Си. Другое дело, что они требуют переучивания, и их просто не было в середине 80-х.

И на нём реально написать файловую систему?

gaa ★★
()
Ответ на: комментарий от gaa

>> Насколько приближенная производительность устроит? 8)

> Чем ближе, тем лучше :)

Скорость работы - это хотя и важный критерий, но не всегда главный. Ocaml, в некотором смысле, проще Си++, при этом оперирует более выскоуровневыми абстракциями.

>> Вообще-то Ocaml (и, наверное, другие языки ML-семейства) выдает 50% производительности Си. Другое дело, что они требуют переучивания, и их просто не было в середине 80-х.

> И на нём реально написать файловую систему?

Разве что через FUSE. Но и Си++ для ядерного кода мало применяется.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>> Вот покажите мне язык с производительностью приближенной к сишной и возможностью легко оперировать ненавистными Absurd-у листами, мапами и алгоритмами с ними?

D - 80-90% прозводительности Си. Полного переучивания не требует.

Ещё, возможно, функциональный Clean с производительностью на уровне 75-80%. Только он совсем не ОО.

naryl ★★★★★
()
Ответ на: комментарий от naryl

> D - 80-90% прозводительности Си. Полного переучивания не требует.

Не, на новый язык без pattern matching я не согласен :)

> функциональный Clean

Он же мертворожденное академическое поделие, не?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

> Не, на новый язык без pattern matching я не согласен :)

Именно поэтому ждём релиза D2 в конце осени. :)

В презентации Уолтера Брайта и Андрея Александреску на страницах 45-51 всё сказано: http://s3.amazonaws.com/dconf2007/WalterAndrei.pdf

naryl ★★★★★
()
Ответ на: комментарий от tailgunner

>> Факты в треде у меня в основном.

>У тебя в основном бредовое истолкование фактов.

Извини, я не догматик. Мог бы конечно процитировать Строуструпа - что он понимает под инкапсуляцией и полиморфизмом, привести его аргументацию почему в С++ есть и то и то и придти к консенсусу с тобой. Но по мне два синтаксических сахара obj.method() вместо method(obj) и obj->ftable->method(obj) вместо аналогичного виртуального вызова ни на инкапсуляцию ни на полиморфизм не катят.

Absurd ★★★
()
Ответ на: комментарий от gaa

>Плюсам она удалась лучше других. Вот покажите мне язык с производительностью приближенной к сишной и возможностью легко оперировать ненавистными Absurd-у листами, мапами и алгоритмами с ними?

Я не ненавижу ни листы ни мапы. Только они должны быть раздельно компилируемыми либо вообще атомарными. А кроме того еще более полезны B* деревья, но их в STL нет и в правила кодирования STL их засунуть тяжело.

Absurd ★★★
()
Ответ на: комментарий от gaa

Дык библиотеки-то - не ОО. Ибо в плюсах нормального ОО нет. Производительность - да, есть. Если постоянно помнить о кучу "спрятанного" кода и держать себя в руках. Т.е. реально в голове постоянно транслировать плюсовый код в сишный.

svu ★★★★★
()
Ответ на: комментарий от gaa

>> Вообще-то Ocaml (и, наверное, другие языки ML-семейства) выдает 50% производительности Си. Другое дело, что они требуют переучивания, и их просто не было в середине 80-х.

>И на нём реально написать файловую систему?

Как будто есть файловая система на С++, бгг.

Absurd ★★★
()
Ответ на: комментарий от gaa

>> Постановка _взаимоисключающих_ целей - верный путь к провалу.

>Вот интеловцы-то не знают. Клепают, бедные, библиотеки для высокопроизводительных вычислений на плюсах, о провале не ведают...

Ты уже специализировал std::valarray для максимального использования SSE2 ?

Absurd ★★★
()
Ответ на: комментарий от gaa

> Вот покажите мне язык с производительностью приближенной к сишной и возможностью легко оперировать ненавистными Absurd-у листами, мапами и алгоритмами с ними?

Лисп. Про мапы не уверен, не проверял, а вот листы очень быстро работают.

mv ★★★★★
()
Ответ на: комментарий от Absurd

> Как будто есть файловая система на С++, бгг

ну насмешил :))))) реализаций доступа к различным фс написано дай боже на самых разных языках :)

> Дык библиотеки-то - не ОО. Ибо в плюсах нормального ОО нет. Производительность - да, есть. Если постоянно помнить о кучу "спрятанного" кода и держать себя в руках. Т.е. реально в голове постоянно транслировать плюсовый код в сишный.

п%здежь и провокация, уж извините за выражения :) то что на с++ можно написать запутанный код не означает, что его надо писать, или что это невозможно сделать в других языках, а то что вы называете "спрятанным" кодом это один-два стандартных макроса в начале файла/описания класса( если уж вдруг есть надобность в том же RTTI - хотя реально он нафиг не нужен ), которые находятся на виду, и если вы не в состоянии единожды их запомнить( почитав подробную документацию того же wx к примеру ), тогда да - ваш удел пользоваться другими языками, но об качестве языка этого ничего не говорит - это говорит о вашей неспособности запомнить пару строк ;) и я не увидел НИ ОДНОГО практического примера, где ООП на с++ хуже чем ООП на яве к примеру, даже наоборот - ваши( противников с++ ) примеры были гораздо хуже реализации на с++( одно только использование списка методов для чтения конфига это чесно говоря п%здец - за такое руки отрывать надо :) ), или работа с плагинами, там где вы предлагали использовать список методов для построения меню( за что так же следует отрывать руки - так как сторониий человек хер догадается об этом раз, а во вторых этот тот самый случай, когда надо "помнить о кучу "спрятанного" кода и держать себя в руках" ), так что давайте вернемся на землю и будем ближе к практике ;)

lester ★★★★
()
Ответ на: комментарий от lester

> то что на с++ можно написать запутанный код не означает, что его надо писать

Означает то, что его пишут.

> это один-два стандартных макроса в начале файла/описания класса

Нет. Это перегруженные операторы (особенно - операторы приведения типов и конструкторы копирования). При чем тут макросы?

> я не увидел НИ ОДНОГО практического примера, где ООП на с++ хуже чем ООП на яве

Ага. Т.е. рефлексию придумали академики, чтоб кто-то защитил диссерт. Нюню.

> работа с плагинами, там где вы предлагали использовать список методов для построения меню

Настоятельно предлагаю посмотреть туториал по junit. Там очень хорошо сделано - ВСЕ методы в testsuite являются тестами. И никому не надо создавать доп. конфигурацию или что-то там еще.

Еще один пример - создание всяческих динамических проксей для middleware. Например, из ejb в corba или наоборот.

svu ★★★★★
()
Ответ на: комментарий от Absurd

> Как будто есть файловая система на С++, бгг.

Ходят упорные слухи о закрытых ФС на Си++. В частности, на lkml я читал, что IBM GFS сделеана на Си++.

tailgunner ★★★★★
()
Ответ на: комментарий от lester

>если уж вдруг есть надобность в том же RTTI - хотя реально он нафиг не нужен

Без RTTI не будет работать dynamic_cast<>.

>одно только использование списка методов для чтения конфига это чесно говоря п%здец - за такое руки отрывать надо

Зачем модулю знать как его будут конфигурировать? Он должен декларировать какие у него есть параметры с помощью метаинформации. Зависимости между модулями должны быть по возможности слабые.

Absurd ★★★
()
Ответ на: комментарий от naryl

> В презентации Уолтера Брайта и Андрея Александреску на страницах 45-51 всё сказано: http://s3.amazonaws.com/dconf2007/WalterAndrei.pdf

Я прочитал это еще тогда, когда ты первый раз постил ссылку :) Там нет нужного pattern matching - как в Ocaml, Erlang, Nemerle :/

tailgunner ★★★★★
()
Ответ на: комментарий от svu

> Означает то, что его пишут.

его пишут на всех языках, или вы не согласны? :)

> Нет. Это перегруженные операторы (особенно - операторы приведения типов и конструкторы копирования). При чем тут макросы?

не пользуйтесь перегруженными операторами - вас никто не заставляет делать того, что вы не понимаете, а параметры надо передавать как const I_Object& inObject - просто из соображений оптимизации

> Ага. Т.е. рефлексию придумали академики, чтоб кто-то защитил диссерт. Нюню.

ну опять 25, какая ПРАКТИЧЕСКАЯ ПОЛЬЗА от этого? рефлексия - это по сути просто замена интерфейсов, что отнюдь не плюс, а источник новых багов и неоднозначностей( junit пока не трогаем - про него ниже ), более того, рефлексия - это и есть прямое запутывание кода и связей в рамках проекта

> Настоятельно предлагаю посмотреть туториал по junit

вы не поверите, но тулзы для автоматического тестирования ООП кода есть и для с++( и в большом количестве ) - гугль в помощь, но если вам не нравится, что они как-то обходятся без рефлексии, то конечно мы не будем этого учитывать ;)

> Еще один пример - создание всяческих динамических проксей для middleware. Например, из ejb в corba или наоборот.

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


lester ★★★★
()
Ответ на: комментарий от tailgunner

>> Как будто есть файловая система на С++, бгг.

>Ходят упорные слухи о закрытых ФС на Си++. В частности, на lkml я читал, что IBM GFS сделеана на Си++.

Нужно же бабос как-то осваивать, иначе в следующий раз не дадут.

Absurd ★★★
()
Ответ на: комментарий от Absurd

>>> Как будто есть файловая система на С++, бгг.

>> Ходят упорные слухи о закрытых ФС на Си++. В частности, на lkml я читал, что IBM GFS сделеана на Си++.

> Нужно же бабос как-то осваивать

Ну то есть ты не будешь больше бггкать на тему того, что на Си++ не написано ни одной ФС? ;)

tailgunner ★★★★★
()
Ответ на: комментарий от lester

Червячог, рефлексия - вещь полезная. Она не зря включена в CORBA. Подумай о маршалинге, сериализации - они с рефлексией делаются проще, чем любыми другими методами.

tailgunner ★★★★★
()
Ответ на: комментарий от lester

> его пишут на всех языках, или вы не согласны? :)

Из моей практики - хреновый код на плюсах разгребать особенно погано. Сравним только перл. Жабский хреновый код разгребается очень легко.

> вас никто не заставляет делать того, что вы не понимаете

Дык оно ж просится! Тут перегружу, там перегружу - а потом люди будут использовать мой код и думать, чего это оно так тормозит...

> а параметры надо передавать как const I_Object& inObject - просто из соображений оптимизации

А нефиг ВООБЩЕ было оставлять в языке передачь объектов по значению. Это абсолютное зло.

> рефлексия - это и есть прямое запутывание кода и связей в рамках проекта

Я уже сказал, в 99% случаев - да. Но бывает нужно написать некий "общий" код, который будет работать в "неизвестных" условиях. И тогда без рефлексии ... приходится изобретать рефлексию вручную.

> насчет проксей - выгода есть только если имена методов совпадают 1:1

Неправда. Несложный конфиг-файл позволит замапить имена методов (опять таки, флаг Вам в руки реализовывать это в плюсах без рефлексии). Но даже и 1:1 в плюсах это не сделать без специального слоя "рефлексии вручную".

> в противном случае код на с++ и той же яве будет практически идентичным

Маппинг имен методов (конфигурируемый в рантайме) делается на жабке парой строк. В плюсах - куча геморрою.

Вообще-то, мы уже пошли на второй круг про рефлексию. Мысль о том, что в том 1% случаев, когда рефлексия нужна (причем этот 1% вполне реалистичен и жизнен), плюсы сразу "проседают" - разрушить не удается.

Compile-time OO - это fake.

svu ★★★★★
()
Ответ на: комментарий от tailgunner

>>> Ходят упорные слухи о закрытых ФС на Си++. В частности, на lkml я читал, что IBM GFS сделеана на Си++.

>> Нужно же бабос как-то осваивать

>Ну то есть ты не будешь больше бггкать на тему того, что на Си++ не написано ни одной ФС? ;)

Вопрос в том, что считать С++. Вполне возможно что расширения файлов у них .cxx, или .cpp. Но этого я бы сказал недостаточно.

Absurd ★★★
()
Ответ на: комментарий от Absurd

> Вполне возможно что расширения файлов у них .cxx, или .cpp. Но этого я бы сказал недостаточно.

Насколько я понял, там были классы, наследование и виртуальные функции. Конечно, без доступа к коду нельзя сказать, какой там уровень использования специфических фишек.

tailgunner ★★★★★
()
Ответ на: комментарий от Absurd

> Без RTTI не будет работать dynamic_cast<>
я имел ввиду не встроенный с++ RTTI - он есть, но весьма ограниченный, а надстройку, которая вынуждает использовать макросы при описании класса, но при этом дает полноценный RTTI

> Зачем модулю знать как его будут конфигурировать? Он должен декларировать какие у него есть параметры с помощью метаинформации. Зависимости между модулями должны быть по возможности слабые.

модуль должен сам себя конфигурировать - т.к. лучше него об этом никто не знает :) а то что вы сейчас предлагаете можно реализвать и без рефлексии, которая создает невменяемый код и вынуждает просматривать( держать в голове ) больше кода, чтоб понять что ж тут происходит и в каком соб-но месте надо внести изменения :)

lester ★★★★
()
Ответ на: комментарий от svu

> Мысль о том, что в том 1% случаев, когда рефлексия нужна

в 99% случаев требуется скорость выполнения и малое потребление ресурсов, я выбираю 99% :)

lester ★★★★
()
Ответ на: комментарий от lester

> подумай о том, что ты долбоеб - может на многое по другому посмотришь

А конкретнее?

tailgunner ★★★★★
()
Ответ на: комментарий от svu

> /me предвидит требования к Absurd вслед за определением Ъ ОО вынести определение Ъ С++.

Нет, просто если мы пишем изолированный кусок кода, например Filesystem, то можем ограничиться чем-то минималистичным, например наследованием и виртуальными функциями.

Внешних библиотек не используем, Экзепшены отключаем, RAII не используется, компилер тим сидит на соседнем этаже, все получается замечательно.

Проблемы начинаются когда мы пишем не изолированный кусок кода, например пользуемся библиотекой которая генерирует экзепшены.

Absurd ★★★
()
Ответ на: комментарий от Absurd

еще раз - ты писал( если память мне не изменяет ), что у тебя главная проблема кинуть исключение из catch, как бы это не соотносится с "Экзепшены отключаем", насчет удаления ресурсов простая конструкция вида:

bool opened = false;
try
{
extObj->OpenExt( ... );
opened = true;
}
catch(...)
{
}

if( opened )
{
...
}

delete extObj;

прекрасно все решает, можно плз повторить какие проблемы возникают - т.к. сам использую такие либы, граблей никаких не встречал

lester ★★★★
()
Ответ на: комментарий от lester

>еще раз - ты писал( если память мне не изменяет ), что у тебя главная проблема кинуть исключение из catch, как бы это не соотносится с "Экзепшены отключаем", насчет удаления ресурсов простая конструкция вида:

Это проблема более широкого, я бы сказал этического плана. Дело в том что лучшие библиотеки которые можно использовать в С++ коде это Plain C библиотеки. Посему уродовать их врапперами на Си++ и завязывать клиентов производного кода на Си++ это своего рода вандализм.

Absurd ★★★
()
Ответ на: комментарий от lester

> ну опять 25, какая ПРАКТИЧЕСКАЯ ПОЛЬЗА от этого? рефлексия - это по сути просто замена интерфейсов, что отнюдь не плюс, а источник новых багов и неоднозначностей( junit пока не трогаем - про него ниже ), более того, рефлексия - это и есть прямое запутывание кода и связей в рамках проекта

Да реальные пацаны вообще сразу хреначат в маш.кодах, им этот ассемблерный сахар вообще не нужен, только на кнопки больше раз давить, толку никакого. Что уж тут говорить про более "высокоуровневые" языки, которые дают возможность неосилившим Ъ дзен клепать говнокод. Если программист не может по номеру эрраты назвать, что это за баг в процессоре, и как его нужно обходить, то пусть берёт метлу в руки или идёт на рынок торговать помидорами, нефиг ему штаны перед вычислителной техникой протирать.

mv ★★★★★
()
Ответ на: комментарий от lester

> прекрасно все решает

Прекрасно проблему освобождения ресурсов в исключительных ситуациях решают финализаторы. А если ещё и GC есть, то ещё лучше.

mv ★★★★★
()
Ответ на: комментарий от mv

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

lester ★★★★
()
Ответ на: комментарий от mv

у нас в основном все на smart_ptr, так что подобный код используется только при работе с гуем( тобто с wxWidgets )

lester ★★★★
()
Ответ на: комментарий от lester

Писькомерство и лишняя головная боль - это писать на языке с неоднородным и сложным синтаксисом. И вести себя, как будто ты элита, раз на этой хрени что-то ваяешь.

mv ★★★★★
()
Ответ на: комментарий от mv

у как мы говорим - "на этой хрени", сразу видно мега кул хацкера, которому Страуструп и в подметки не годится :) правда таких на ЛОРе полно, которые кричат - пыхпых отстой, джава дерьмо, с++ херня и т.п. ;)

lester ★★★★
()
Ответ на: комментарий от lester

> надень очки - это был ответ грубостью на грубость

Я просто принял тебя не за того. Впрочем, полезность рефлексии это не отменяет.

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.