Помощь - Поиск - Пользователи - Календарь
Полная версия: Отлов утечек памяти - GNAT
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
Страницы: 1, 2
volvo
Цитата
Как раз тогда лучше в ANSI из блокнота сохранить, чтобы воспринимать русское 'а' как один символ.
У меня системная кодировка = Hebrew (win 1255), не будет сохранено 'а' одним символом, сохранится 'HEBREW LETTER ALEF'. Именно поэтому я говорю всем, кто начинает писать юникодные программы: "пишите их на машине, где системная кодировка либо вообще нейтральная (английская), либо какая-нибудь экзотическая, не совпадающая с той, которая (как вам кажется) должна стоять у всех. Это вам только кажется, системную кодировку каждый волен выбирать по своему вкусу и по своим потребностям, а не по потребностям вашей программы. Будете писать при non-unicode = Cyrillic - пользователи будут огребать проблемы, источников которых вы не поймете, ибо у вас будет работать, у других - зависит от положения Луны на небе. Повезет - сработает, нет - не сработает"

Цитата
А, всё оказалось проще. Я работаю с УТФ-8, но для всех процедур принимаю именно просто-строку (не юникод), которую для юникодных компонентов переделываю через MultiByteToWideChar с константой CP_UTF8 : constant WORD := 65001, скопированной из System.Win32
Это будет работать ровно до тех пор, пока ты не перекомпилируешь свою программу на машине с некириллической системной страницей (Китай, Индия, Япония, все азиатские страны, ну, и Израиль в том числе, практически гарантированно пролетают, потенциально - любая машина, на которой non-unicode не выставлен в Cyrillic. Я на такой риск пойти не могу, наши программы работают не только на одной машине, и пересобираются тоже в разных странах, так что вся работа делается через юникодные файлы). Вот тогда ты поймешь, что значит бардак с кодировками...
TarasBer
> Это будет работать ровно до тех пор, пока ты не перекомпилируешь свою программу на машине с некириллической системной страницей

Русские утф-8 символы останутся же русскими утф-8 символами? И функция перекодировки останется та же с теми же параметрами. Что изменится?
volvo
Цитата
для всех процедур принимаю именно просто-строку (не юникод)
Ты можешь гарантировать, что "просто строка" не будет на той реализации, где программа перекомпилируется, зависеть от системной кодировки, и что компилятором не будет предприниматься никаких автоматических действий с НЕюникодной строкой? Вот по отношению к юникоду я уверен в этом: никаких перекодировок не будет. Как только дело касается не Wide_String/Wide_Wide_String, а просто String - уверенным ни в чем быть нельзя. Стандарт не гарантирует...
TarasBer
Я уверен только в том, что на другой машине, где стоит ГНАТ, настроенный на УТФ-8, будет перекомпилировываться корректно. Я ведь могу быть в этом уверен?
Вариант не лучший, но ждать, когда в ГНАТ добавят нормальный АНСИ или исправят баг?
TarasBer
Решил я применить расширенный возврат к функции преобразования массива в вектор (кстати, почему её нет стандартной?), ну, чтобы не копировать лишнее.


function To_Vector(a: Key_Arr) return Key_Based_Vectors.Vector is

Arr_Index: Integer := a'First;

procedure Update(Item: in out Key_Base) is
begin
Item := A(Arr_Index);
Arr_Index := Arr_Index + 1;
end Update;

procedure Copy(C: Key_Based_Vectors.Cursor) is

type Public_Cursor is record
Container : access Key_Based_Vectors.Vector;
Index : integer;
end record;

function Fuck_Cursor is new Ada.Unchecked_Conversion(Key_Based_Vectors.Cursor, Public_Cursor);

begin
-- где логика в стандартном контейнере?
-- нафига этой процедуре принимать контейнер, если она и так принимает курсор?
-- где стандартная функция преобразования массива в вектор?
-- где стандартная обратная функция?
Update_Element (Fuck_Cursor©.Container.all, C, Update'Access);
end Copy;

use Key_Based_Vectors;

begin
return V: Key_Based_Vectors.Vector do
Set_Length(V, A'Length);
V.Iterate (Copy'Access);
end return;
end To_Vector;



Не, не скомпилилось.

parser.adb:31:10: no candidate interpretations match the actuals:
parser.adb:31:51: expected private type "Ada.Containers.Vectors.Vector" from instance at parser.ads:28
parser.adb:31:51: found private type "Ada.Containers.Vectors.Vector" from instance at parser.ads:29
parser.adb:31:51: ==> in call to "Update_Element" at a-convec.ads:134, instance at parser.ads:28
parser.adb:31:51: ==> in call to "Update_Element" at a-convec.ads:129, instance at parser.ads:28

Это не вектор, это вектор, а не вектор, а нужен именно вектор.

Зато я только сейчас заметил, что в Аде можно в итераторы кидать локальные подпрограммы, в Дельфи приходилось в глобальную область всякую фигню выводить. Там типа неявно стек копируется?
volvo
Внимательнее будь. Это основа успеха при освоении Ады. Смотри:

use Func_Tree_Vectors;  --  Это у тебя было, правда?

function To_Vector(a: Key_Arr) return Key_Based_Vectors.Vector is

Arr_Index: Integer := a'First;

procedure Update(Item: in out Key_Base) is
begin
Item := A(Arr_Index);
Arr_Index := Arr_Index + 1;
end Update;

use Key_Based_Vectors; -- Вот эта строка была на несколько строк ниже ...

procedure Copy(C: Key_Based_Vectors.Cursor) is

type Public_Cursor is record
Container : access Key_Based_Vectors.Vector;
Index : integer;
end record;

function Fuck_Cursor is new Ada.Unchecked_Conversion(Key_Based_Vectors.Cursor, Public_Cursor);

begin
Update_Element (Fuck_Cursor ( C ).Container.all, C, Update'Access);
end Copy;

begin
return V: Key_Based_Vectors.Vector do
Set_Length(V, A'Length);
V.Iterate (Copy'Access);
end return;
end To_Vector;
, и уже все компилируется. Почему надо было переносить use выше, понятно? Если бы она была там, где ее написал ты, то доступен только один Update_Element: из пакета Func_Tree_Vectors, чей use присутствует выше по тексту. А эта функция должна принимать другой тип контейнера, о чем Ада тебе пыталась сказать. Номера строк, в которых инстанцирован "Ada.Containers.Vectors.Vector" не просто так даются, можно было посмотреть, что происходит в этих строках...

Как только use перенесен выше по тексту, уже доступна и вторая процедура Update_Element, из Key_Based_Vectors. Тут уже компилятор способен по параметрам разобраться, какую из перегруженных версий вызывать...
TarasBer
И всё-таки, как это сделать без непроверенной конверсии с идеологически неверным кулхацкеровским "раздеванием" курсора?
Если унаследовать свой вектор от этого, то я получу доступ к его приватным полям и возможность написать преобразование нормально?
volvo
Цитата
И всё-таки, как это сделать без непроверенной конверсии с идеологически неверным кулхацкеровским "раздеванием" курсора?
Да легко:

function To_Vector(a: Key_Arr) return Key_Based_Vectors.Vector is

Arr_Index: Integer := a'First;

procedure Update(Item: in out Key_Base) is
begin
Item := A(Arr_Index);
Arr_Index := Arr_Index + 1;
end Update;

use Key_Based_Vectors;
begin
return V: Key_Based_Vectors.Vector do

declare

procedure My_Copy(C: Key_Based_Vectors.Cursor) is
begin
V.Update_Element (C, Update'Access);
end My_Copy;

begin
Set_Length(V, A'Length);
V.Iterate (My_Copy'Access);
end;

end return;
end To_Vector;
Где "раздевание" курсора? Где конверсии? Нету... Однако, компилируется без проблем. Но вот контейнер должен быть описан выше по коду, чем процедура обработки. А к вопросу
Цитата
нафига этой процедуре принимать контейнер, если она и так принимает курсор?
ответ - такой: Чтоб без подобных выкрутасов, как ты сделал (с непроверенными конверсиями и другими кулхацкерскими штучками) не позволить тебе изменить с помощью Update_Element константный контейнер (было бы слишком просто: получил Курсор, передал его в Update_Element, и все, прощай константность вектора? Нет уж, лучше так, как сейчас...). Безопасность превыше всего. Кстати, изначально в А2005 была-таки версия Update_Element, которая принимала всего 2 параметра: Курсор и Процесс. Но это была дыра в безопасности, и ее очень быстро закрыли...
TarasBer
Это уже получше.
И ещё вопрос: как унаследоваться от стандартного вектора так, чтобы сохранить все операции над ним?

type Vector is new Vectors.Vector with record
null;
end record;

type Cursor is new Vectors.Cursor;

Позволяет работать с операциями над чисто контейнером, но не позволяет работать с операциями, в которых участвует курсор.
volvo
Непонятно, зачем наследоваться от отдельного типа, если можно сразу получить весь функционал пакета? На кой наследование-то? Как хочешь его использовать потом? Что инстанцировать собрался? Всё, что описано в Ada.Containers.Vector - оно дженериковое вообще-то, в любом случае надо где-то говорить, с какими типами это все будет работать. Так зачем делать несколько разрозненных типов, если можно настроить весь пакет, и его полноценно использовать?

P.S.
Цитата
type Vector is new Vectors.Vector with record
null;
end record;
- это устаревшая запись. Уже давно можно делать
type Descendant is new Base with null record;

Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.