Ada_Ru форум

Обсуждение языка Ада

Корректность использования перегрузки

Оставить новое сообщение

Сообщения

rainbow-2000
Корректность использования перегрузки
2006-03-09 05:23:17

Друзья,

 

У меня вопрос по поводу использования одного и того же значка для разных операций. В C++, например, это обычное дело. Очень удобно перегружать что-нибудь вроде <<, для вывода значений переменных класса с помощью средств ostream.

Дозволяется ли перегрузка в Ada и если да, то есть ли какая-то гарантия корректности её использования (т.е., что определённый символ, используемый для определённой операции на вполне определённых аргументах, всегда будет давать вполне определённый результат и другого быть не может).

Подскажите пожалуйста, где об этом можно почитать.

 

Алексей

rainbow-2000 wrote:

 

Дозволяется ли перегрузка в Ada и если да, то есть ли какая-то гарантия корректности её использования (т.е., что определённый символ, используемый для определённой операции на вполне определённых аргументах, всегда будет давать вполне определённый результат и другого быть не может).

Да, перегрузка большинства операций в языке позволяется (исключение пожалуй только одно - "/=" - её перегрузить нельзя), причём возможность перегрузки шире, чем в C++, а именно тип возвращаемого значения тоже принимает участие в разрешении перегруженного имени, т.е.

 

function "+" (L, R : Integer) return Integer;

 

function "+" (L, R : Integer) return Float;

 

есть две разные подпрограммы.

 

"Гарантия" правильности использования следует из контекста видимости. Что из того, что видно подходит - то и используется. Из этого могут выплыть и глюки, например:

 

package A is

 

function "mod" (V : Integer) return Integer;

 

-----------------------

package B is

 

function "mod" (V : Integer) return Integer;

 

-----------------------

with A; use A;

with B; use B;

 

package C is

 

X : Integer := 5;

Z : Integer := mod (X);

 

то уж извините, но какой "mod" использовать - не понятно.

 

 

PS. Переопределение операторов в Ada рекомендуется только при наличии логической связи между знаком операции и выполняемыми действиями. Таким образом, если рассматривать C++, то использование сдвига влево/вправо для операций ввода/вывода есть нарушение рекомендации.

 

 

-- Vadim Godunko

 

Technoserv A/S

Rostov-on-Don, Russia

Vadim Godunko wrote:

 

>package A is

 

function "mod" (V : Integer) return Integer;

 

>-----------------------

>package B is

 

function "mod" (V : Integer) return Integer;

 

>-----------------------

>with A; use A;

>with B; use B;

 

>package C is

 

X : Integer := 5;

Z : Integer := mod (X);

 

>то уж извините, но какой "mod" использовать - не понятно.

 

 

Насколько я понял, GNAT не даст откомпилировать код, если ему не

понятно, какой mod надо вызывать.

Так что глюков тут в Ада не будет. А вот насчет С++ не знаю.

Vadim Godunko wrote:

 

Да, перегрузка большинства операций в языке позволяется (исключение пожалуй только одно - "/=" - её перегрузить нельзя), причём возможность перегрузки шире, чем в C++, а именно тип возвращаемого значения тоже принимает участие в разрешении перегруженного имени, т.е.

..................

логической связи между знаком операции и выполняемыми действиями. Таким образом, если рассматривать C++, то использование сдвига влево/вправо для операций ввода/вывода есть нарушение рекомендации.

 

 

 

Благодарю за пояснения. Да, похоже вопрос не так прост, как кажется на первый взгляд. Было бы конечно здорово, если бы такие гарантии корректности перегрузки чётко были прописаны где-нибудь в стандарте Ada (А может быть так оно и есть?).

 

Да, C++ язык очень гибкий и определённая логика в использовании << конечно есть (направление потока). Конечно глюков там было достаточно, но надо признать, что качество компиляторов C++ существенно улучшилось за последние годы.

 

Алексей

Благодарю за пояснения. Да, похоже вопрос не так прост, как кажется на первый взгляд. Было бы конечно здорово, если бы такие гарантии корректности перегрузки чётко были прописаны где-нибудь в стандарте Ada (А может быть так оно и есть?).

 

А как же! Многие разделы стандарта содержат подраздел "Name Resolution Rules"

 

Кроме того, есть раздел 8.6 "The Context of Overload Resolution".

 

А в целом - Вадим все уже сформулировал: для каждого перегруженного оператора

должна существовать ровно одна корректная интерпретация (ровно одно подходящее

видимое определение). Поиск подходящих интерпретаций осуществляется на

основе контекста, определеяемого в разделе 8.6, на основе подходящих

Name Resolution Rules и Legality Rules.

 

Все просто и однозначно...

 

Да, C++ язык очень гибкий и определённая логика в использовании << конечно есть (направление потока). Конечно глюков там было достаточно, но надо признать, что качество компиляторов C++ существенно улучшилось за последние годы.

 

Компилятор не может исправить исходную корявость языка.

 

Тут вчерась мой младший ребенок в полубезумном состоянии с дикими матами

выскочил из-за компутера. Он впервые открыл для себя, что эффект

программы существенно зависит от того, в каком порядке идут include.

 

Ну каким компилятором ТАКОЕ можно компенсировать?!

А в целом - Вадим все уже сформулировал: для каждого перегруженного оператора должна существовать ровно одна корректная интерпретация (ровно одно подходящее видимое определение). Поиск подходящих интерпретаций осуществляется на основе контекста, определеяемого в разделе 8.6, на основе подходящих Name Resolution Rules и Legality Rules.

 

Все просто и однозначно...

 

Какие-то однако с этим непонятности. Если взять пример Вадима, и сделать что mod из пакета А выдает 1, mod из пакета В выдает 2, а потом с данным описанием контекста сделать 5 mod 5, программа прекрасно скомпилируется и выдаст...... ноль! То есть пользовательские перегрузки оператора были компилятором нагло ни словечка не сказав спрятаны. То ли я чего-то не понимаю то ли имеем глюк.

 

Ну каким компилятором ТАКОЕ можно компенсировать?!

 

Это, все же, проблемы не языка а препроцессора. Внедрение аналога препроцессора непосредственно в язык, как в Аде, это все же исключение а не правило. Да и потом, мне ли вам рассказывать сколько приятных минут мы в результате из года в год проводим с этими чертовыми generics? :)

 

ВФ

"Гарантия" правильности использования следует из контекста видимости. Что из того, что видно подходит - то и используется. Из этого могут выплыть и глюки, например:

 

package A is

 

function "mod" (V : Integer) return Integer;

 

-----------------------

package B is

 

function "mod" (V : Integer) return Integer;

 

-----------------------

with A; use A;

with B; use B;

 

package C is

 

X : Integer := 5;

Z : Integer := mod (X);

 

то уж извините, но какой "mod" использовать - не понятно.

 

Па-а-а-а-а-а-звольте!!!

 

RM 95, 8.4 (9, 10):

 

9 A declaration is use-visible if it is potentially use-visible, except in these naming-conflict cases:

 

10 · A potentially use-visible declaration is not use-visible if the place considered is within the immediate scope of a homograph of the declaration.

 

 

Оба эти операции mod не будут ВИДИМЫ в точке вызова, и будет

вызвана ПРЕДОПРЕДЕЛЕННАЯ операция mod из пакета Standard!

>>Все просто и однозначно...

 

 

Какие-то однако с этим непонятности. Если взять пример Вадима, и сделать

что mod из пакета А выдает 1, mod из пакета В выдает 2, а потом с данным

описанием контекста сделать 5 mod 5, программа прекрасно скомпилируется и

выдаст...... ноль! То есть пользовательские перегрузки оператора были

компилятором нагло ни словечка не сказав спрятаны. То ли я чего-то не

понимаю то ли имеем глюк.

 

Спасибо, что ткнули пальцем, а то я поначалу проскочил. Вадим просто

ошибся в правилах видимости - там тоже все просто и однозначно :))

 

Нет, на самом деле есть завиральные места, но:

 

1. Где их нет?

2. В Аде их все же меньше, чем где бы то ни было.

 

Ну каким компилятором ТАКОЕ можно компенсировать?!

 

 

Это, все же, проблемы не языка а препроцессора. Внедрение аналога

препроцессора непосредственно в язык, как в Аде, это все же исключение а не

правило. Да и потом, мне ли вам рассказывать сколько приятных минут мы в

результате из года в год проводим с этими чертовыми generics? :)

 

А вот и не согласен! Это - проблемы, в изобилии проистекающие из

попытки реализовать МОДУЛЬНОСТЬ на основе препроцессора!

 

generic в Аде - аналог template в С++, а вовсе не аналог

препроцессору как инструменту сборки многомодульных программ.

 

Глюки вокруг generic в Аде разумно сравнивать с глюками вокруг

template в С++, а вот попробуйте сравнить Адскую

модульность на основе спецификаций контекста и понятия среды компиляции

с Си-шной "модульностью" на основе этих дурацких инклюдов!

Vasiliy Fofanov wrote:

А в целом - Вадим все уже сформулировал: для каждого перегруженного оператора

должна существовать ровно одна корректная интерпретация (ровно одно подходящее

видимое определение). Поиск подходящих интерпретаций осуществляется на

основе контекста, определеяемого в разделе 8.6, на основе подходящих

Name Resolution Rules и Legality Rules.

 

Все просто и однозначно...

 

Какие-то однако с этим непонятности. Если взять пример Вадима, и сделать

что mod из пакета А выдает 1, mod из пакета В выдает 2, а потом с данным

описанием контекста сделать 5 mod 5, программа прекрасно скомпилируется и

выдаст...... ноль! То есть пользовательские перегрузки оператора были

компилятором нагло ни словечка не сказав спрятаны. То ли я чего-то не

понимаю то ли имеем глюк.

 

Интересно, mod для Integer есть примитивная подпрограмма, да ещё и с соглашениями Intrinsics. Может тут правила видимости, а может и глюк.

 

 

-- Vadim Godunko

 

Technoserv A/S

Rostov-on-Don, Russia

Спасибо, что ткнули пальцем, а то я поначалу проскочил. Вадим просто ошибся в правилах видимости - там тоже все просто и однозначно :))

 

Должно быть просто. И как правило действительно так и есть - "multiple use clauses cause hiding" тыкскть. Но конкретно в примере Вадима что-то компилятор себя повел странновато. Надо разбираться...

 

А вот и не согласен! Это - проблемы, в изобилии проистекающие из попытки реализовать МОДУЛЬНОСТЬ на основе препроцессора!

 

Да, согласен. Но немало проблем также проистекало из попыток реализовать объектную ориентированность на основе настраиваемых пакетов в Аде 83 :) Тут скорее тогда уж не кривость а нехватка языковых возможностей, что не то же самое...

 

Глюки вокруг generic в Аде разумно сравнивать с глюками вокруг

template в С++

 

В С++ есть полноценная поддержка ООП, никто это там через темплэйты и не подумает делать :)

 

ВФ

Интересно, mod для Integer есть примитивная подпрограмма, да ещё и с соглашениями Intrinsics. Может тут правила видимости, а может и глюк.

 

Я спросил совета наших языковых зубров, их слово будет закон :)

 

ВФ.

Оба эти операции mod не будут ВИДИМЫ в точке вызова, и будет

вызвана ПРЕДОПРЕДЕЛЕННАЯ операция mod из пакета Standard!

 

Ах вот оно что... понятно. Извиняюсь за шум, письма мне приходят в странноватом порядке...

 

ВФ

Да, согласен. Но немало проблем также проистекало из попыток реализовать

объектную ориентированность на основе настраиваемых пакетов в Аде 83 :) Тут

скорее тогда уж не кривость а нехватка языковых возможностей, что не то же

самое...

 

Ну дык! ООП через generic в Аде 83 - это ж героизьм на грани безумства!

Vasiliy Fofanov wrote:

Оба эти операции mod не будут ВИДИМЫ в точке вызова, и будет

вызвана ПРЕДОПРЕДЕЛЕННАЯ операция mod из пакета Standard!

 

 

Ах вот оно что... понятно. Извиняюсь за шум, письма мне приходят в

странноватом порядке...

 

ВФ

 

 

Друзья,

 

Большое спасибо за дискуссию. А насчёт писем - это верно. Я их тоже получаю в каком-то случайном порядке. Не очень понятна линия обсуждения, пока все письма не получишь :) .

 

Алексей

Новое сообщение:
Страницы: 1

Чтобы оставить новое сообщение необходимо Зарегистрироваться и Войти