Здравствуйте, c-smile, Вы писали: CS>1) имплементация const как он есть в C++. Со всеми вытекающими за и против.
CS>2) введение двух новых метатипов readonly array & pointer, типа такого:
CS> char#[] — readonly array CS> char#* — readonly pointer.
А чего не как в си-шарп с ключевым словом readonly?
Здравствуйте, Александр Сергеевич, Вы писали:
АС>Здравствуйте, c-smile, Вы писали: CS>>1) имплементация const как он есть в C++. Со всеми вытекающими за и против.
CS>>2) введение двух новых метатипов readonly array & pointer, типа такого:
CS>> char#[] — readonly array CS>> char#* — readonly pointer.
АС>А чего не как в си-шарп с ключевым словом readonly?
C# readonly не есть то же самое что const char[] в С++ —
задача в основном состоит в том чтобы можно было
изобразить такое:
void foo( const char[] s )
Т.е. такая декларация предполагает что содержимое
массива s внутри функции foo не изменится.
Здравствуйте, c-smile, Вы писали:
CS>Без наличия чего-то типа const char[] имплементация строк CS>в классическом виде невозможна.
Очень смешно. И как Ява с Шарпом живут?
Про immutable-типы слышал? Если в языке нормально поддерживается инкапсуляция, то нет проблем создать тип экземпляры которого можно будет только создавать, но нельзя будет изменять. Далее дело техники. Примеры в той же Яве и Шарпе.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, c-smile, Вы писали:
CS>>Без наличия чего-то типа const char[] имплементация строк CS>>в классическом виде невозможна.
VD>Очень смешно. И как Ява с Шарпом живут?
VD>Про immutable-типы слышал? Если в языке нормально поддерживается инкапсуляция, то нет проблем создать тип экземпляры которого можно будет только создавать, но нельзя будет изменять. Далее дело техники. Примеры в той же Яве и Шарпе.
Я ж про это и говорю.
const char[] - immutable.
char[] - mutable.
В C# и Java проблема (проблема ли?) — нет понятия deep immutable:
int foo(in MyClass cls)
in защищает от изменения переменную cls в вызывающей процедуре
но сам объект передаваемый — конем гуляй по нему.
const MyClass& cls в C++ означает что для cls объекта в классе
MyClass подавлены все изменяющие методы.
immutable — это характиристика типа. const же всего лишь предохраняет от модификации переменной.
CS>В C# и Java проблема (проблема ли?) — нет понятия deep immutable: CS>
CS>int foo(in MyClass cls)
CS>
CS>in защищает от изменения переменную cls в вызывающей процедуре CS>но сам объект передаваемый — конем гуляй по нему.
Объект или передается по значению и тогда хоть обмодифицируйся. Или по ссылке. При этом возмжность модификации объекта зависит от того ползволяет ли он себя модифицировать.
Например, попроубуй изменить в C# строку или значение типа DateTimr.
CS>const MyClass& cls в C++ означает что для cls объекта в классе CS>MyClass подавлены все изменяющие методы.
Нет. cls означет, что ссылка недопускает модфикации объекта. В то же время всегда можно создать новую ссылку или указатель и модифицировать через него тот же объект. Модифицировать же immutable-объект невозможно.
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>immutable — это характиристика типа. const же всего лишь предохраняет от модификации переменной.
C точки зрения формальной логики
class A{...};
const A a;
const A есть образование нового типа A' у которого отсутвуют (или закрыты) все мутирующие методы.
immutability может быть "ручной" и "автоматической" — в С# доступна только "ручная". В C++ и первая и вторая.
CS>>В C# и Java проблема (проблема ли?) — нет понятия deep immutable: CS>>
CS>>int foo(in MyClass cls)
CS>>
CS>>in защищает от изменения переменную cls в вызывающей процедуре CS>>но сам объект передаваемый — конем гуляй по нему.
VD>Объект или передается по значению и тогда хоть обмодифицируйся. Или по ссылке. При этом возмжность модификации объекта зависит от того ползволяет ли он себя модифицировать.
VD>Например, попроубуй изменить в C# строку или значение типа DateTimr.
Я ж и говорю — зависит от ручной импелементации. В Java например String immutable а DateTime — нет.
Автоматической — нет.
CS>>const MyClass& cls в C++ означает что для cls объекта в классе CS>>MyClass подавлены все изменяющие методы.
VD>Нет. cls означет, что ссылка недопускает модфикации объекта. В то же время всегда можно создать новую ссылку или указатель и модифицировать через него тот же объект. Модифицировать же immutable-объект невозможно.
Мы говорим не про mutability enforcment, а про нормальное использование.
Из-за того что в C++ используется deep immutability который(ая) есть вещь суровая, то для практических целей оставлен
const_cast<> — явное снятие immutability.
Полный режим readonly возможен только на хардверном уровне.
Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, c-smile, Вы писали:
CS>"И ниччо ему золота рыба не сказала..."
Так ничего удивительного, имхо. Из любителей D на этом форуме я могу припомнить тебя, uw и Зверька Харьковского.
CS>deep immutable references — C++ const CS>shallow immutable references — предлагаемый вариант (#)
CS>Тогда вопрос — а нужно ли оно вообще?
Это ты про D?
Имхо, что-то подобное, определенно, нужно. Меня в Java очень добивало то, что объекты передавались в методы по ссылке, но никак нельзя было запретить методу модифицировать объект.
Как C++ник, думаю, что нужно делать аналог C++ const. Хотя выльется это, вероятно, в очень серьезную модификацию D. И, кроме того, придется поддерживать mutable-атрибуты у объектов. Кстати, в первом посте ты сказал: "1) имплементация const как он есть в C++. Со всеми вытекающими за и против". А что под "против" понимается?
Ну а второй вариант мне даже синтаксически не нравится. Использование спецсимволов для обозначения характеристик объектов -- это, имхо, прямой путь к perl-подобному синтаксису.
И еще во втором варианте меня вот что смущает. Я уже не помню D толком, но кажется там есть понятие указателей и есть операция разыменования указателя (ты сам сказал: "у readonly указателя нет опреации dereferencing to l-value"). Это позволяет делать на шаблонах что-то вроде (синтаксис C++):
template< class T >
T f( T * p ) { T c = *p; ...; return c; }
т.е., если f() вызывается для const T *, то T внутри шаблона будет иметь тип const T.
А если в D сделать readonly pointer, то не введет ли это новую абстракцию "readonly pointer", который вроде как pointer, но не такой? И не создаст ли это сложностей при программировании тех же шаблонов?
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
VD>>immutable — это характиристика типа. const же всего лишь предохраняет от модификации переменной.
CS>C точки зрения формальной логики
CS>
CS>class A{...};
CS>const A a;
CS>
CS>const A есть образование нового типа A' у которого отсутвуют (или закрыты) все мутирующие методы.
Нет здесь никакой логики. const всего лишь модификатор распространяющийся на переменную. Самому объекту от этого не горячо и не холодно. Вот такой код тебя ведь не смущат:
class A { };
void main()
{
A* a1 = new A();
const A* a2 = a2;
}
При этом a1 можно менять, а a2 нет. Но по твоим словам у них разный тип.
CS>immutability может быть "ручной" и "автоматической" — в С# доступна только "ручная". В C++ и первая и вторая.
В С# доступна инкапсуляция которая позволяет создать immutability-объекты. Отальное от лукавого.
Главное, что этого достаточно для создания immutability-классов решающих поставленную проблему.
CS>Я ж и говорю — зависит от ручной импелементации.
Как меня раздражает эта твоя "импелементации"... если бы ты знал.
CS> В Java например String immutable а DateTime — нет. CS>Автоматической — нет.
А зачем автоматическое? Это характиристика типа. Пусть тот кто проектирует тип и определяет эту характиристику.
Причем я как бы не спорю, что нечто вроде readonly для локальных переменных очень не помешало бы в Шарпе. Но immutable тем не менее — это характеристика класса. Это можно сказать паттерн проектрования. И никакие const его не заменят.
Тут уж было бы разумно говорить о ключевом слове (или атрибуте) immutable применяемом к классу. Ну, чтобы запретить модификацию полей вне конструктора (т.е. дополнительная проверка).
CS>Мы говорим не про mutability enforcment,
Ну, пошли иностранные ругательства.
CS> а про нормальное использование.
Дык что есть нормальное это еще очень большой вопрос.
CS>Из-за того что в C++ используется deep immutability который(ая) есть вещь суровая, то для практических целей оставлен CS>const_cast<> — явное снятие immutability.
Это ты себе придумываешь. С++ предоставляет возможность локальной защиты в виде объявления переменных как неизменяемыми. Ничего "глубокого" тут нет.
Как показывает практика при работе в рамках подхода когда сам тип определяет возможность своей модификации эта константность не так уж и необходима. Скорее возникает ощущение отсуствие того к чему привык. Но это проходит.
CS>Полный режим readonly возможен только на хардверном уровне.
Ну почему же? Если у меня полностью типобезопасный язык и язык действительно декларирует, что "A != const A", то он обязан гарантировать невозможность изменения объектов типа const A. Просто С++ никогда не бы типобезопасным. Только и всего. Да и const в нем все же трактуется как модификатор переменной.
... << RSDN@Home 1.2.0 alpha rev. 516>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
CS>>Из-за того что в C++ используется deep immutability который(ая) есть вещь суровая, то для практических целей оставлен CS>>const_cast<> — явное снятие immutability.
VD>Это ты себе придумываешь. С++ предоставляет возможность локальной защиты в виде объявления переменных как неизменяемыми. Ничего "глубокого" тут нет.
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, c-smile, Вы писали:
CS>>Здравствуйте, c-smile, Вы писали:
CS>>"И ниччо ему золота рыба не сказала..."
E>Так ничего удивительного, имхо. Из любителей D на этом форуме я могу припомнить тебя, uw и Зверька Харьковского.
CS>>deep immutable references — C++ const CS>>shallow immutable references — предлагаемый вариант (#)
CS>>Тогда вопрос — а нужно ли оно вообще?
E>Это ты про D?
E>Имхо, что-то подобное, определенно, нужно. Меня в Java очень добивало то, что объекты передавались в методы по ссылке, но никак нельзя было запретить методу модифицировать объект.
E>Как C++ник, думаю, что нужно делать аналог C++ const. Хотя выльется это, вероятно, в очень серьезную модификацию D. И, кроме того, придется поддерживать mutable-атрибуты у объектов. Кстати, в первом посте ты сказал: "1) имплементация const как он есть в C++. Со всеми вытекающими за и против". А что под "против" понимается?
E>Ну а второй вариант мне даже синтаксически не нравится. Использование спецсимволов для обозначения характеристик объектов -- это, имхо, прямой путь к perl-подобному синтаксису.
В общем-то не так.
typename [] — означает массив элементов типа typename
typename #[] — означает immutable массив элементов типа typename.
Т.е. для лексера #[ это один токен. Примерно так же как << и <<=
Т.е. # не есть синоним слова const.
E>И еще во втором варианте меня вот что смущает. Я уже не помню D толком, но кажется там есть понятие указателей и есть операция разыменования указателя (ты сам сказал: "у readonly указателя нет опреации dereferencing to l-value"). Это позволяет делать на шаблонах что-то вроде (синтаксис C++): E>
E>template< class T >
E>T f( T * p ) { T c = *p; ...; return c; }
E>
E>т.е., если f() вызывается для const T *, то T внутри шаблона будет иметь тип const T. E>А если в D сделать readonly pointer, то не введет ли это новую абстракцию "readonly pointer", который вроде как pointer, но не такой? И не создаст ли это сложностей при программировании тех же шаблонов?
Мысль понял. Спасибо. В предлагаемом варианте получентие значения по ссылке все та же
*.
Т.е.
f<char*>( p )
f<char#*>( p )
будут одинаково работать.
Спец. символы в общем не must.
Проблема в том что например const в С++ означает две или три разные сущности.
Eugene Pelekhay предложил например вариант когда все массивы
по определению read-only:
: // function returns mutable string
: var char[] func1(){}
: // function returns immutable string
: char[] func2(){}
: // function with argument of immutable string
: void func3(char[] s) {}
: // function with argument of reference to immutable string
: // reference assigned during function call and content can't be
: // changed in caller trough returned reference
: void func4(out char[] s) {}
: // function with argument of initialized immutable string
: // that reference can be changed during function call
: void func5(inout char[] s) {}
: // function with argument of mutable string
: // content of string can be changed during function call
: void func6(var char[] s) {}
: // function with argument of reference to mutable string
: // content of string can be changed outside of function
: // through returned reference
: void func7(out var char[] s) {}
: // function with argument of reference to initialized mutable string
: // content of string can be changed outside of function or during call
: // through returned/passed reference
: void func8(inout var char[] s) {}
Это тоже так называемая shallow immutability ( см. ссылки в моих ответах Владу )
Считается (не мной) что попытка сделать deep immutability как в C++ чревата
а) многословием (const everywhere) b) уровень верификации immutability не является достаточным
(a.k.a. овчинка выделки не стоит)
Shallow immutability используется в Deplphi насколько мне известно
Здравствуйте, VladD2, Вы писали:
VD>Тогда напиши в МС, что у них в компиляторе серьезный баг, так как вот такой код:
5.2.8 Type identification
...
The top-level cv-qualifiers of the lvalue expression or the type-id that is the operand of typeid are always ignored. [Example:
class D { ... };
D d1;
const D d2;
typeid(d1) == typeid(d2); // yields true
typeid(D) == typeid(const D); // yields true
typeid(D) == typeid(d2); // yields true
typeid(D) == typeid(const D&); // yields true
—end example]
3.9.3 CV-qualifiers
A type mentioned in 3.9.1 and 3.9.2 is a cv-unqualified type. Each type which is a cv-unqualified complete or incomplete object type or is void (3.9) has three corresponding cv-qualified versions of its type: a const-qualified version, a volatile-qualified version, and a const-volatile-qualified version. The term object type (1.8) includes the cv-qualifiers specified when the object is created. The presence of a const specifier in a decl-specifier-seq declares an object of const-qualified object type; such object is called a const object.
Здравствуйте, VladD2, Вы писали:
VD>То есть ты хочешь сказать, что объект A меняет свой тип будучи присвоеным в константную переменную?
Нет, он присваиваеся объекту другого типа. В том, что CV-квалификация входит в тип выражения (скажем, в отличие от ссылки), можно легко убедиться анализируя как производится вывод типов аргументов шаблонов по аргументам функции. Или просто посмотреть на то, как вводится CV-квалификация в стандарте:
3.9.3 CV-qualifiers [basic.type.qualifier]
1 A type mentioned in 3.9.1 and 3.9.2 is a cv-unqualified type. Each type which is a cv-unqualified complete or incomplete object type or is void (3.9) has three corresponding cv-qualified versions of its type: a const-qualified version, a volatile-qualified version, and a const-volatile-qualified version. The term object type (1.8) includes the cv-qualifiers specified when the object is created. The presence of a const specifier in a decl-specifier-seq declares an object of const-qualified object type; such object is called a const object. The presence of a volatile specifier in a decl-specifier-seq declares an object of volatile-qualified object type; such object is called a volatile object. The presence of both cv-qualifiers in a declspecifier-seq declares an object of const-volatile-qualified object type; such object is called a const volatile object. The cv-qualified or cv-unqualified versions of a type are distinct types; however, they shall have the same representation and alignment requirements (3.9).
VD>Тогда напиши в МС, что у них в компиляторе серьезный баг, так как вот такой код: VD>
Да, хороший пример. Для typeid, т.к. CV-квалифицированные версии являются отдельными типами, присутствует специальное правило, предписывающее именно для целей typeid считать типы, отличающиеся только CV-квалификацией верхнего уровня, идентичными (5.2.8/5).
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
E>5.2.8 Type identification
E>...
E>The top-level cv-qualifiers of the lvalue expression or the type-id that is the operand of typeid are always ignored. [Example:
E>class D { ... };
E>D d1;
E>const D d2;
E>typeid(d1) == typeid(d2); // yields true
E>typeid(D) == typeid(const D); // yields true
E>typeid(D) == typeid(d2); // yields true
E>typeid(D) == typeid(const D&); // yields true
E>—end example]
E>
E>3.9.3 CV-qualifiers
E>A type mentioned in 3.9.1 and 3.9.2 is a cv-unqualified type. Each type which is a cv-unqualified complete or incomplete object type or is void (3.9) has three corresponding cv-qualified versions of its type: a const-qualified version, a volatile-qualified version, and a const-volatile-qualified version. The term object type (1.8) includes the cv-qualifiers specified when the object is created. The presence of a const specifier in a decl-specifier-seq declares an object of const-qualified object type; such object is called a const object.
Ну, тоесть стандарт противоречит сам себе? Или это все же не тип в полном понимании этого слова?
... << RSDN@Home 1.1.4 beta 7 rev. 466>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.