Re[3]: Почему нельзя писать void ctor();
От: Mr.Delphist  
Дата: 18.10.17 11:54
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Это понятно. Но я думал, что void как раз и означает что функция не возвращает СОВСЕМ НИКАКОГО значения. Это не так?


Нет, не так. void — это специальный тип-пустышка, тип-джокер.

void foo(void *p)
{
    int x = (int)p; // трактуем указатель p как обычное целое число
    int y = *(int*)p; // трактуем указатель p как указатель на целое число и сразу разыменовываем
    int z = ******************************************************(int******************************************************)p; // это компилируется, я проверял
    void *wut = (void*)( p ? (int)p ^ (int)p : (int)p % (int)p); // ну, мне пора :)
}
Re[2]: Почему нельзя писать void ctor();
От: kov_serg Россия  
Дата: 18.10.17 12:26
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, Максим Рогожин, Вы писали:


МР>>Отличается ли из-за этого низкоуровневая организация вызова этой функции (организация стека, пролог, эпилог)?


Pzz>Нет, просто договоренность такая, что конструктор не имеет явно указанного возвращаемого типа. Конструктор в любом случае — особая функция, и компилятор понимает, как для него организовывать стек и прочий пролог.


А меня всегда удивляло почему нельзя было для конструктора и деструктора зарезервировать какие-нибудь имена, а не писать имя класса каждый раз.
И почему private выбрали по умолчанию вместо public. Не говоря уже об отсутствие аккумулятора и возрате последнего значения как в perl
Типа такого

// header

class A : B {
   ctor();
   dtor();
   nonvirtual void fn();
   void gn()=0; 
};

// impl

implement class A {
  ctor() { ... }
  dtor() { ... }
  void fn() { parent::member(); }
}

А указатели на методы класса всегда вызывали смутные эмоции.
Re[3]: Почему нельзя писать void ctor();
От: Pzz Россия https://github.com/alexpevzner
Дата: 18.10.17 12:58
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>А меня всегда удивляло почему нельзя было для конструктора и деструктора зарезервировать какие-нибудь имена, а не писать имя класса каждый раз.


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

_>И почему private выбрали по умолчанию вместо public.


Это как-раз правильно. Если бы все члены классов были по умолчанию public, то у индусов в программах вообще все члены были бы всегда public, и никакого ограничения видимости никто бы не использовал.

_>Не говоря уже об отсутствие аккумулятора и возрате последнего значения как в perl


Это я не слишком-то понял.

_>А указатели на методы класса всегда вызывали смутные эмоции.


А меня, после знакомства с Go, стало бесить, что в Си операторы . и -> разные. Казалось бы, компилятор и так знает, что стоит слева, структура или указатель на структуру, и хватили бы одного оператора на оба случая...
Re[4]: Почему нельзя писать void ctor();
От: kov_serg Россия  
Дата: 18.10.17 13:14
Оценка:
Здравствуйте, Pzz, Вы писали:

_>>Не говоря уже об отсутствие аккумулятора и возрате последнего значения как в perl

Pzz>Это я не слишком-то понял.
int min(int x,int y) { if (x<y) x; else y; }
int x={ if (a<0) 0; else a; };

min(z[0],z[1]); min(_,z[2]); min(_,z[3]);
int last_result=_;


_>>А указатели на методы класса всегда вызывали смутные эмоции.

Pzz>А меня, после знакомства с Go, стало бесить, что в Си операторы . и -> разные. Казалось бы, компилятор и так знает, что стоит слева, структура или указатель на структуру, и хватили бы одного оператора на оба случая...
да стрелку могли бы приспособить для правого присвоения
10+2*5 -> a
Re[5]: Почему нельзя писать void ctor();
От: Pzz Россия https://github.com/alexpevzner
Дата: 18.10.17 13:19
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>
_>int min(int x,int y) { if (x<y) x; else y; }
_>int x={ if (a<0) 0; else a; };

_>min(z[0],z[1]); min(_,z[2]); min(_,z[3]);
_>int last_result=_;

_>


У gcc есть такое расширение. Но в принципе, эта конструкция — источник глупых ошибок. Откуда компилятору знать, я действительно имел ввиду последнее значение в блоке, или просто забыл сказать return где-то в середине?

Pzz>>А меня, после знакомства с Go, стало бесить, что в Си операторы . и -> разные. Казалось бы, компилятор и так знает, что стоит слева, структура или указатель на структуру, и хватили бы одного оператора на оба случая...

_>да стрелку могли бы приспособить для правого присвоения
_>10+2*5 -> a

Угу. А еще надо присваивание вверх и вниз:

int           a, b;
              ^
b = 10 + (2*5)|;


Промежуточное значение заносим в переменную a, а окончательный результат — в переменную b.
Re[4]: Почему нельзя писать void ctor();
От: Pzz Россия https://github.com/alexpevzner
Дата: 18.10.17 13:26
Оценка:
Здравствуйте, rg45, Вы писали:

R>Эти две записи похожи лишь формально. Только в первом случае это является не возвращением значения, а прямым конструированием объекта в правой части инициализатора. Это то же самое выражение, которое используется в операторе return в функции createObject:


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

А чтобы жизнь им окончательно не казалось медом, пространство имен функций и пространство имен типов — это разные пространства. Т.е., в принципе, имя функции может совпадать с именем класса, и поэтому надо сначала пытаться найти имя среди имен функций, а потом — среди имен типов.
Re[4]: Почему нельзя писать void ctor();
От: Pzz Россия https://github.com/alexpevzner
Дата: 18.10.17 13:28
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Для чего запрещать конструктору возвращать даже void, но при этом разрешать следующий синтаксис?


МР>
МР>A obj = A(1024);
МР>


Чтобы можно было сконструировать временный объект, и не засосывать его явно в какую-либо переменную.
Re[6]: Почему нельзя писать void ctor();
От: kov_serg Россия  
Дата: 18.10.17 13:36
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Здравствуйте, kov_serg, Вы писали:


_>>
_>>int min(int x,int y) { if (x<y) x; else y; }
_>>int x={ if (a<0) 0; else a; };

_>>min(z[0],z[1]); min(_,z[2]); min(_,z[3]);
_>>int last_result=_;

_>>


Pzz>У gcc есть такое расширение. Но в принципе, эта конструкция — источник глупых ошибок.

Pzz>Откуда компилятору знать, я действительно имел ввиду последнее значение в блоке, или просто забыл сказать return где-то в середине?
return это выход из функции. А тут последнее значение можно передавать в функцию по умолчанию
(неявно как this) при этом жесткая типизация и шаблоны позволили бы сделать очень интересные вещи.

Pzz>>>А меня, после знакомства с Go, стало бесить, что в Си операторы . и -> разные.

Pzz>>>Казалось бы, компилятор и так знает, что стоит слева, структура или указатель на структуру, и хватили бы одного оператора на оба случая...
_>>да стрелку могли бы приспособить для правого присвоения
_>>10+2*5 -> a

Pzz>Угу. А еще надо присваивание вверх и вниз:


Pzz>
Pzz>int           a, b;
Pzz>              ^
Pzz>b = 10 + (2*5)|;
Pzz>

Pzz>Промежуточное значение заносим в переменную a, а окончательный результат — в переменную b.
Вы чертов гений! Надо вообще сделать 10+2*5->(goto +10,-2) или 10+2*5->(looks like z[] or has prefix result_) или 0->(all unsigned)
Вообще rightward operator иногда очень даже удобен
https://stat.ethz.ch/R-manual/R-devel/library/base/html/assignOps.html

ps: Напомню: "что настоящий ученый может писать фортраном на любом языке"
Re[4]: Почему нельзя писать void ctor();
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.10.17 07:26
Оценка:
Здравствуйте, Pzz, Вы писали:

_>>А меня всегда удивляло почему нельзя было для конструктора и деструктора зарезервировать какие-нибудь имена, а не писать имя класса каждый раз.

Pzz>Ну например за тем, чтобы не вводить еще одного ключевого словак, которое, тем самым, станет недоступным в качестве идентификатора.

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

Представим себе язык, где $ — префикс "это всегда идентификатор", а @ — "это всегда ключевое слово"; без префикса — есть список стандартно понимаемых ключевых слов (и в некоторых контекстах может расширяться). Допустить даже варианты типа $"a b c", если кому-то нужны такие дикие идентификаторы.
Тогда можем получать и любые идентификаторы, и возможность пробных расширений языка на новые использования. Захотел какое-нибудь @foomode — добавил без конфликта; устоялось — объявил, что через 3 года будет пониматься без '@' — у всех есть время переключиться.

На самом деле тот же C# частично начал двигаться в эту сторону за счёт рекомендации стиля использовать заглавные для любого внешнего идентификатора — зона конфликта резко сокращается и, что главное, обычно не выходит за пределы внутренностей модуля. Go это формализовал до конца — там заглавная обязательна для экспорта, ключевые слова только со строчной, и они не опасаются за устойчивость любых пользовательских API против этого расширения.

А писать init вместо CVeryLongAndTerribleApiBeastFactory, по-моему, достаточно удобно

_>>И почему private выбрали по умолчанию вместо public.


Pzz>Это как-раз правильно. Если бы все члены классов были по умолчанию public, то у индусов в программах вообще все члены были бы всегда public, и никакого ограничения видимости никто бы не использовал.


Pzz>А меня, после знакомства с Go, стало бесить, что в Си операторы . и -> разные. Казалось бы, компилятор и так знает, что стоит слева, структура или указатель на структуру, и хватили бы одного оператора на оба случая...


Почему Go, меня и после Python и Java это удивляет хорошо хоть ошибки обычно тривиальные.
The God is real, unless declared integer.
Re[6]: Почему нельзя писать void ctor();
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.10.17 07:29
Оценка:
Здравствуйте, Pzz, Вы писали:

_>>
_>>int min(int x,int y) { if (x<y) x; else y; }
_>>int x={ if (a<0) 0; else a; };

_>>min(z[0],z[1]); min(_,z[2]); min(_,z[3]);
_>>int last_result=_;

_>>


Pzz>У gcc есть такое расширение. Но в принципе, эта конструкция — источник глупых ошибок. Откуда компилятору знать, я действительно имел ввиду последнее значение в блоке, или просто забыл сказать return где-то в середине?


А это надо решать точно так же, как с проблемой if (a = b): требовать явной пометки таких случаев. Вводим новое слово — например, take.

if (a == b) — нет проблем.
if (take a = b) — нет проблем, при чтении чётко понятно, что тут ещё и присвоение.
if (a = b) — не компилируется, присвоение без take не имеет понятия результата.
a = take b = take c = 0 — побочный эффект, чуть больше слов. Но такие конструкции сейчас очень редки, так что можно потерпеть.
a = take if (x > 0) x; else -x; — явно берём результат ifʼа, компилятор знает, что блоки внутри if должны выдавать значение.

Pzz>Угу. А еще надо присваивание вверх и вниз:


The God is real, unless declared integer.
Re[2]: Почему нельзя писать void ctor();
От: _hum_ Беларусь  
Дата: 19.10.17 20:55
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, Максим Рогожин, Вы писали:


МР>>Почему нельзя писать так


МР>>class A {

МР>>public:
МР>> void A() {}
МР>>};
МР>>?

N>Страуструп писал, что это для подчёркивания того факта, что конструктор никогда не зовётся напрямую.



МР>>Отличается ли из-за этого низкоуровневая организация вызова этой функции (организация стека, пролог, эпилог)?


N>Вот принятое в Unix ABI, например, знает


  code
N>
N>  <ctor-dtor-name> ::= C1    # complete object constructor
N>           ::= C2    # base object constructor
N>           ::= C3    # complete object allocating constructor
N>           ::= D0    # deleting destructor
N>           ::= D1    # complete object destructor
N>           ::= D2    # base object destructor
N>


N>В этом случае тот конструктор, что с C3, аллоцирует память и возвращает адрес объекта, а те, что C1 и C2, получают первым скрытым параметром адрес объекта и ничего не возвращают.


N>Больше отличий нет, остальное идентично обычной функции.


N>Для MSVC правил не знаю, могут быть хитрости.



так а, действительно, что тогда мешает официально изменить семантику конструктора на вариант наподобие "создает объект класса и инициализирует его, после чего возращает ссылку на этот объект"?
(токо недавно обсуждали, что, например, в таком случае такое новое понятие, как User-defined deduction guides, можно было бы тогда свести к декларации шаблона такого конструктора. это я к тому, что, возможно, это могло бы помочь с введением новых нужных понятий через уже старые.)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.