Re: Приведение базового класса в конструкторе потомка
От: rg45 СССР  
Дата: 02.09.19 14:37
Оценка: 12 (1) +5
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>
ЕМ>struct Base {
ЕМ>  int a;
ЕМ>  int b;
ЕМ>};

ЕМ>struct Derived : public Base {
ЕМ>  Derived (Base const B) { *this = B; }
ЕМ>};

ЕМ>Derived f (Base const B) {
ЕМ>  return B;
ЕМ>}
ЕМ>


ЕМ>Можно ли как-то заставить компилятор приводить типы совсем тупо? Ни reinterpret_cast, ни function-style cast, ни C-style cast не помогают.


Про списки инициализации не слыхал?

struct Derived : public Base {
  Derived (Base const B) : Base(B) { }
};


P.S. Я уже не спрашиваю, почему параметр передается по значению, почему конструктор не explicit и зачем оно вообще нужно.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Приведение базового класса в конструкторе потомка
От: Zhendos  
Дата: 02.09.19 18:39
Оценка: +1 -1
Здравствуйте, cserg, Вы писали:

C>Здравствуйте, Евгений Музыченко, Вы писали:


ЕМ>>Можно ли как-то заставить компилятор приводить типы совсем тупо? Ни reinterpret_cast, ни function-style cast, ни C-style cast не помогают.

C>Вот такое разве не работает?
C>
C>Derived(Base const B) { (*(Base*)this) = B; }
C>


по-моему что-нибудь типа
Derived(Base const B) { this->Base::operator=(B); }


будет намного более понятнее чем приведение указателей
Re[8]: Приведение базового класса в конструкторе потомка
От: Mystic Artifact  
Дата: 04.09.19 11:41
Оценка: 8 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

MA>> Как бы я не извращался — результат в rax. На clang тоже в rax.

ЕМ>А это уже странно. Они ж должны быть совместимы по ABI.
Что-то вчера был не мой день видимо. Я и проект собирал, ошибся и пол дня он висел без дела, пока я не заметил.

В моём примере: msvc x64 v19.22 для method и virtual_method возвращается адрес на структуру, для static_method возвращается сама структура по значению.
А вот clang 8.0 — в обоих случаях возвращает структуру по значению (через регистр). С -O1 тела методов вообще идентичны.

Насчет должны быть совместимы по ABI — то, афаик, windows abi отличается от amd64 abi.

Вроде как похоже, что поведение вполне соответствует документации Calling Conventions: Return Values.

A scalar return value that can fit into 64 bits is returned through RAX; this includes __m64 types. Non-scalar types including floats, doubles, and vector types such as __m128, __m128i, __m128d are returned in XMM0. The state of unused bits in the value returned in RAX or XMM0 is undefined.

User-defined types can be returned by value from global functions and static member functions. To return a user-defined type by value in RAX, it must have a length of 1, 2, 4, 8, 16, 32, or 64 bits. It must also have no user-defined constructor, destructor, or copy assignment operator; no private or protected non-static data members; no non-static data members of reference type; no base classes; no virtual functions; and no data members that do not also meet these requirements. (This is essentially the definition of a C++03 POD type. Because the definition has changed in the C++11 standard, we don't recommend using std::is_pod for this test.) Otherwise, the caller assumes the responsibility of allocating memory and passing a pointer for the return value as the first argument. Subsequent arguments are then shifted one argument to the right. The same pointer must be returned by the callee in RAX.


Похоже на правду?
Отредактировано 04.09.2019 11:45 Mystic Artifact . Предыдущая версия .
Re: Приведение базового класса в конструкторе потомка
От: kov_serg Россия  
Дата: 02.09.19 14:40
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>стабильно жалуются на то, что конструктор Derived получается рекурсивным за счет того, что для преобразования Base к Derived используется он же.

А если написать так:
struct Derived : public Base {
 Derived(Base const B) : Base(B) { }
};
Re[2]: Приведение базового класса в конструкторе потомка
От: Hobbes Россия  
Дата: 02.09.19 20:09
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>P.S. Я уже не спрашиваю, почему параметр передается по значению, почему конструктор не explicit и зачем оно вообще нужно.


Передача параметра конструктора по значению в сочетании с std::move — стильно, модно, молодёжно. Но тут Евгений чертовщину какую-то делает. Особенно, если он пытается сделать инициализацию базы.
Re[3]: Приведение базового класса в конструкторе потомка
От: rg45 СССР  
Дата: 03.09.19 05:17
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Чтобы оптимизатор делал передачу структур до 64 разрядов через регистры. Впрочем, для не-POD этого, похоже, не добиться — он всегда генерит временную переменную, даже если по факту никаких вызовов конструкторов/деструкторов там нет (все вычисляется во время компиляции).


R>>почему конструктор не explicit

ЕМ>Именно, чтобы можно было преобразовывать неявно.

Я думаю, тебе полезно будет освежить в памяти рекомендации из этой чудесной книженции:

C++ Coding Standards. 101 Rules, Guidelines, and Best Practices.
(Цитаты взяты из русского перевода книги).

Правило №8. Не оптимизируйте преждевременно

Передача параметров по ссылке (рекомендация 25), использование префиксной формы операторов ++ и -- (рекомендация 28) или подобных идиом, которые при работе должны естественным образом "стекать с кончиков ваших пальцев", преждевременной оптимизацией не являются. Это всего лишь устранение преждевременной пессимизации (рекомендация 9).


Правило №9. Не пессимизируйте преждевременно

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


Правило №15. Активно используйте const

Пример. Избегайте const в объявлениях функций, принимающих параметры по значению. Два следующих объявления абсолютно эквивалентны:

void Fun( int x );
void Fun( const int x );  // Объявление той же самой функции:
                          // const здесь игнорируется

Во втором объявлении модификатор const избыточен. Мы рекомендуем объявлять функции без таких высокоуровневых модификаторов const, чтобы тот, кто читает ваши заголовочные файлы, не был дезориентирован...


Правило №40. Избегайте возможностей неявного преобразования типов

Не все изменения прогрессивны: неявные преобразования зачастую приносят больше вреда, чем пользы. Дважды подумайте перед тем, как предоставить возможность неявного преобразования к типу и из типа, который вы определяете, и предпочитайте полагаться на явные преобразования (используйте конструкторы, объявленные как explicit, и именованные функции преобразования типов).

--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 03.09.2019 8:04 rg45 . Предыдущая версия . Еще …
Отредактировано 03.09.2019 8:03 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 5:56 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 5:54 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 5:43 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 5:29 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 5:25 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 5:20 rg45 . Предыдущая версия .
Re[6]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 12.09.19 08:29
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>объекты небольших структур с недорогим копированием, типа твоего Base, вполне допустимо передавать по значению.


Кстати, еще вспомнил, где это может быть полезно — при работе с множественными значениями типа HRESULT. Стандартно SUCCEEDED/FAILED — это макросы, можно сделать и через глобальные функции, но правильнее было бы оформить HRESULT в виде объекта со встроенными методами анализа, форматирования и т.п.

Но для таких вполне достаточно конструктора, оператора присваивания и методов обработки, а вот для других подобных структур было бы очень удобно иметь возможность и возвращать их по значению.
Re[8]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 17.09.19 09:44
Оценка: :)
Здравствуйте, rg45, Вы писали:

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


Да понятно, что реального смысла в такой экономии нет — просто раздражает очевидная странность/тупость компилятора.

R>Так а в чем проблема, возвращай, пожалуйста — все необходимые специальные функции-члены генерируются компилятором автоматически, главное ему не мешать.


Я как посмотрю иногда, сколько кода автоматически генерит компилятор на все эти определения — плакать хочется.
Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 02.09.19 14:22
Оценка:
Компиляторы MS VC++ на такой вот код:

struct Base {
  int a;
  int b;
};

struct Derived : public Base {
  Derived (Base const B) { *this = B; }
};

Derived f (Base const B) {
  return B;
}


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

Это особенность компиляторов MS, или оно везде так?

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

Можно ли как-то заставить компилятор приводить типы совсем тупо? Ни reinterpret_cast, ни function-style cast, ни C-style cast не помогают.

Знаю, что можно включить Base в Derived вместо наследования, и наделать операторов преобразования, но хотелось бы именно с наследованием.
base derived constuctor type conversion cast базовый потомок тип приведение преобразование
Re: Приведение базового класса в конструкторе потомка
От: night beast СССР  
Дата: 02.09.19 14:34
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Компиляторы MS VC++ на такой вот код:


ЕМ>struct Derived : public Base {
ЕМ>  Derived (Base const B) { *this = B; }
ЕМ>};

ЕМ>Derived f (Base const B) {
ЕМ>  return B;
ЕМ>}


ЕМ>стабильно жалуются на то, что конструктор Derived получается рекурсивным за счет того, что для преобразования Base к Derived используется он же.


ссылки нигде не забыл?

давай может лучше напишешь с примерами, что именно хочешь получить в итоге, а то не очень понятно
Re: Приведение базового класса в конструкторе потомка
От: cserg  
Дата: 02.09.19 14:45
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Можно ли как-то заставить компилятор приводить типы совсем тупо? Ни reinterpret_cast, ни function-style cast, ни C-style cast не помогают.

Вот такое разве не работает?
Derived(Base const B) { (*(Base*)this) = B; }
Re[2]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 02.09.19 15:13
Оценка:
Здравствуйте, night beast, Вы писали:

NB>ссылки нигде не забыл?


Нет.

NB>давай может лучше напишешь с примерами, что именно хочешь получить в итоге, а то не очень понятно


Да этого примера достаточно. Нужно, чтобы все передавалось по значению, через регистры.
Re[2]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 02.09.19 15:19
Оценка:
Здравствуйте, rg45, Вы писали:

R>Про списки инициализации не слыхал?


Блин. Я был так удивлен невозможностью преобразования типа, что совсем забыл о том, что инициализируется, по сути, базовый класс.

R>почему параметр передается по значению


Чтобы оптимизатор делал передачу структур до 64 разрядов через регистры. Впрочем, для не-POD этого, похоже, не добиться — он всегда генерит временную переменную, даже если по факту никаких вызовов конструкторов/деструкторов там нет (все вычисляется во время компиляции).

R>почему конструктор не explicit


Именно, чтобы можно было преобразовывать неявно.

R>и зачем оно вообще нужно.


В реальном коде 32-разрядная структура из битовых полей. Ее и удобнее, и выгоднее держать на регистре.
Re[2]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 02.09.19 15:20
Оценка:
Здравствуйте, cserg, Вы писали:

C>Вот такое разве не работает?

C>
C>Derived(Base const B) { (*(Base*)this) = B; }
C>


Работает, как и взятие укаателя на B и приведение его к указателю на Derived. Но при этом все заведомо будет в памяти.
Re[3]: Приведение базового класса в конструкторе потомка
От: Zhendos  
Дата: 02.09.19 17:06
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

R>>почему параметр передается по значению


ЕМ>Чтобы оптимизатор делал передачу структур до 64 разрядов через регистры. Впрочем, для не-POD этого, похоже, не добиться — он всегда генерит временную переменную, даже если по факту никаких вызовов конструкторов/деструкторов там нет (все вычисляется во время компиляции).


можно написать так:

struct Derived : public Base {
 Derived(Base B) : Base(std::move(B)) { }
};
Re[3]: Приведение базового класса в конструкторе потомка
От: cserg  
Дата: 02.09.19 17:15
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Работает, как и взятие укаателя на B и приведение его к указателю на Derived.

Только нельзя так делать.

ЕМ>Но при этом все заведомо будет в памяти.

Вы ошибаетесь. Операция взятия адреса еще не означает, что адресуемый объект обязательно будет размещен в памяти.
Re[4]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 02.09.19 18:27
Оценка:
Здравствуйте, cserg, Вы писали:

ЕМ>>Работает, как и взятие укаателя на B и приведение его к указателю на Derived.


C>Только нельзя так делать.


С чего бы вдруг? Совершенно типовая операция.

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


Теоретически. А практически это умеют только самые зверские оптимизаторы (у MS такого нет).
Re[3]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 02.09.19 18:58
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z> будет намного более понятнее чем приведение указателей


Задача не в понятности, а в избавлении от излишних пересылок.
Re[4]: Приведение базового класса в конструкторе потомка
От: andyp  
Дата: 02.09.19 20:03
Оценка:
Здравствуйте, Zhendos, Вы писали:



Z>можно написать так:


Z>
Z>struct Derived : public Base {
Z> Derived(Base B) : Base(std::move(B)) { }
Z>};
Z>


Имхо B тогда протухает и уже недоступно в теле конструктора, могут быть связанные с этим залеты. А так, для условий ТС (B — куча бит без указателей внутри) особого выигрыша по производительности не будет имхо.
Re[3]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 03.09.19 10:16
Оценка:
Здравствуйте, Hobbes, Вы писали:

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


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

А чертовщина — это то, что в MS VC++, например, обычный метод класса, возвращающий по значению POD-структуру размером до восьми байт, делает это через регистры. Но стоит сделать этот метод виртуальным, как он возвращает то же самое исключительно через временную переменную на стеке. Ладно бы возвращаемый элемент сам был классом, но это банальная POD-структура, которая от класса, в котором определяется метод, никак не зависит. Я в полных непонятках о причине такой особенности.
Re[4]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 03.09.19 10:19
Оценка:
Здравствуйте, rg45, Вы писали:

R>Я думаю, тебе полезно будет освежить в памяти рекомендации из этой чудесной книженции:


Я ее как раз недавно перечитывал. Охотно последую этим советам, если кто-нибудь сумеет внятно объяснить, почему 32-разрядный int "безусловно следует" передавать по значению, а 32-разрядную структуру — столь же "безусловно", но по ссылке.
Re[5]: Приведение базового класса в конструкторе потомка
От: rg45 СССР  
Дата: 03.09.19 11:50
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

R>>Я думаю, тебе полезно будет освежить в памяти рекомендации из этой чудесной книженции:


ЕМ>Я ее как раз недавно перечитывал. Охотно последую этим советам, если кто-нибудь сумеет внятно объяснить, почему 32-разрядный int "безусловно следует" передавать по значению, а 32-разрядную структуру — столь же "безусловно", но по ссылке.


Ну насчет "безусловно" это ты загнул, конечно. Ну ОК, объекты небольших структур с недорогим копированием, типа твоего Base, вполне допустимо передавать по значению. Об этом говорится в рекомендации №25. Однако способом передачи по умолчанию все же является передача по константной ссылке. Генеруемые компилятором конструкторы копирования и копирующие операторы присванивания имеют именно такой вид. Все стандартные шаблонные функции, наподобие push_back, например, принимают параметры по константной ссылке и никого не парит возможная потеря производительности при работе с целыми числами. Ну какой смысл в этом промежуточном копировании в конструкторе Derived, если в итоге копирование пойдет через конструктор копирования Base, который все равно будет работать по константной ссылке на эту промежуточную копию Не лучше ли просто пробросить ему ссылку на оригинал?

Ну а что насчет других рекомендаций — касающихся неявных преобразований и модификаторов const при параметрах? Тоже не согласен с чем-то?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 03.09.2019 12:37 rg45 . Предыдущая версия . Еще …
Отредактировано 03.09.2019 12:35 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 12:34 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 12:30 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 12:14 rg45 . Предыдущая версия .
Отредактировано 03.09.2019 12:07 rg45 . Предыдущая версия .
Re[6]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 03.09.19 13:20
Оценка:
Здравствуйте, rg45, Вы писали:

R>Ну а что насчет других рекомендаций — касающихся неявных преобразований и модификаторов const при параметрах? Тоже не согласен с чем-то?


Разумеется. За использование неявных преобразований имеет смысл пенять только после того, как в языке сделают мало-мальски управляемую систему integral promotions, которая во многих случаях совершенно бессмысленна, и при попытке скрестить ее с шаблонами/перегрузками заставляет городить чрезмерно сложные конструкции. Я на это здесь уже ругался раз
Автор: Евгений Музыченко
Дата: 10.10.17
и два
Автор: Евгений Музыченко
Дата: 09.10.18
.

Модификатор const у параметра-значения в объявлении функции действительно не имеет смысла, но объявление ж не существует само по себе — или оно копируется из заголовка определения, или заголовок определения копируется из него. Если в определениях используется const — какой смысл старательно вычищать его из объявлений, или добавлять в определения после копирования?
Re[4]: Приведение базового класса в конструкторе потомка
От: Hobbes Россия  
Дата: 03.09.19 18:35
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>А чертовщина — это то, что в MS VC++, например, обычный метод класса, возвращающий по значению POD-структуру размером до восьми байт, делает это через регистры. Но стоит сделать этот метод виртуальным, как он возвращает то же самое исключительно через временную переменную на стеке. Ладно бы возвращаемый элемент сам был классом, но это банальная POD-структура, которая от класса, в котором определяется метод, никак не зависит. Я в полных непонятках о причине такой особенности.


Возможно, причина в том, что в compile-time виртуальный метод не знает, в каком контексте его вызовут и чем там будут какие регистры заняты.
Re[5]: Приведение базового класса в конструкторе потомка
От: Mystic Artifact  
Дата: 03.09.19 18:38
Оценка:
Здравствуйте, Hobbes, Вы писали:

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


А не виртуальный знает что-ли?
Re[6]: Приведение базового класса в конструкторе потомка
От: Hobbes Россия  
Дата: 03.09.19 18:50
Оценка:
Здравствуйте, Mystic Artifact, Вы писали:

MA> А не виртуальный знает что-ли?


Ну... в общем случае тоже нет
Re[5]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 03.09.19 22:04
Оценка:
Здравствуйте, Hobbes, Вы писали:

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


Э-э-э... А как он тогда с другими параметрами и возвращаемыми значениями обращается?

Тут больше похоже на то, что когда-то просто облажались, перепутав где-то в таблицах признаки объекта класса и виртуальной функции, а когда это обнаружилось, метаться было уже поздно, и пришлось узаконить.
Re[6]: Приведение базового класса в конструкторе потомка
От: Mystic Artifact  
Дата: 03.09.19 22:17
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Э-э-э... А как он тогда с другими параметрами и возвращаемыми значениями обращается?

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

Я тут на godbolt-е поигрался немного:

#include <utility>

typedef struct {
    int a;
    int b;
} ValueType;

class MyClass {
    public:
    ValueType method(int a, int b) {
        ValueType v;
        v.a = a;
        v.b = b + a;
        return v;
    };

    virtual ValueType virtual_method(int a, int b) {
        ValueType v;
        v.a = a;
        v.b = b + a;
        return v;
    };

    static ValueType static_method(int a, int b) {
        ValueType v;
        v.a = a;
        v.b = b + a;
        return v;
    };
};

int foo(int a, int b) {
  MyClass* x = new MyClass();
  auto v1 = x->method(a, b);
  auto v2 = x->virtual_method(b, a);
  auto v3 = MyClass::static_method(a, b);
  return v1.a + v2.b + v3.a * v3.b;
}


Как бы я не извращался — результат в rax. На clang тоже в rax.
Пример левой пяткой писан, потому, что он мне internal service error почему-то выдавал постоянно, пока его не "передернешь" с -O2 на -O0 и/или назад.
Примечательно, что при -O2 clang всё это выбрасывает нафиг, оставляя суть, а msvc не особо торопиться что-то выбрасывать.
Отредактировано 03.09.2019 22:17 Mystic Artifact . Предыдущая версия .
Re[4]: Приведение базового класса в конструкторе потомка
От: cserg  
Дата: 04.09.19 00:35
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>А чертовщина — это то, что в MS VC++, например, обычный метод класса, возвращающий по значению POD-структуру размером до восьми байт, делает это через регистры. Но стоит сделать этот метод виртуальным, как он возвращает то же самое исключительно через временную переменную на стеке.

А этот обычный метод класса встраиваемый или нет?
Re[7]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 04.09.19 11:28
Оценка:
Здравствуйте, Mystic Artifact, Вы писали:

MA> Как бы я не извращался — результат в rax. На clang тоже в rax.


А это уже странно. Они ж должны быть совместимы по ABI.
Re[5]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 04.09.19 11:29
Оценка:
Здравствуйте, cserg, Вы писали:

C>А этот обычный метод класса встраиваемый или нет?


Какая разница? Компилятор же для любого метода всегда генерит полноценную функцию, которую потом может свернуть при встройке. Именно о ней и речь.
Re[9]: Приведение базового класса в конструкторе потомка
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 04.09.19 12:38
Оценка:
Здравствуйте, Mystic Artifact, Вы писали:

MA> Что-то вчера был не мой день видимо. Я и проект собирал, ошибся и пол дня он висел без дела, пока я не заметил.


И у меня ведь было стойкое убеждение, что я видел, как обычный (нестатический и невиртуальный) метод возвращал структуру по значению.

MA> В моём примере: msvc x64 v19.22 для method и virtual_method возвращается адрес на структуру, для static_method возвращается сама структура по значению.


Такая же хрень.

MA> Вроде как похоже, что поведение вполне соответствует документации Calling Conventions: Return Values.


И правда. Я с этим первые разы экспериментировал еще в 90-х, с тех пор и отложилось. Видать, ни разу не приглядывался с тех пор.

Вот только непонятно, на кой им понадобилось так разделять поведение статических и нестатических членов. Кроме случайной закрепившейся в практике ошибки, на ум ничего не приходит.
Re[10]: Приведение базового класса в конструкторе потомка
От: Mystic Artifact  
Дата: 04.09.19 12:45
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Вот только непонятно, на кой им понадобилось так разделять поведение статических и нестатических членов. Кроме случайной закрепившейся в практике ошибки, на ум ничего не приходит.

Я тоже не понимаю, и скорее всего они сами не понимают, тем более для других компиляторов это не является проблемой.

PS: Я помню, как-то решил обернуть некий то ли указатель, то ли что-то из int в структуру в C# и использовал в PInvoke (просто, что бы добавить какой-то типизированности). И всё работало, ведь на x86 такие структуры возвращаются по значению. Как же я был разочарован когда на линуксе это вообще не поднялось (ведь там они всегда возвращаются по указателю).
Re[7]: Приведение базового класса в конструкторе потомка
От: rg45 СССР  
Дата: 12.09.19 09:10
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:


R>>объекты небольших структур с недорогим копированием, типа твоего Base, вполне допустимо передавать по значению.


ЕМ>Кстати, еще вспомнил, где это может быть полезно — при работе с множественными значениями типа HRESULT. Стандартно SUCCEEDED/FAILED — это макросы, можно сделать и через глобальные функции, но правильнее было бы оформить HRESULT в виде объекта со встроенными методами анализа, форматирования и т.п.


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

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


Так а в чем проблема, возвращай, пожалуйста — все необходимые специальные функции-члены генерируются компилятором автоматически, главное ему не мешать. Ну либо предоставлять собственные версии, когда это действительно необходимо. А начиная с C++17 возвращать по значению можно вообще что угодно, независимо от доступности конструкторов — благодаря guaranteed copy/move elision. Это обсуждалось здесь не так давно: http://rsdn.org/forum/cpp/7421860.1
Автор: _NN_
Дата: 17.04.19
. Или ты снова подразумеваешь возврат через регистры vs возврат черерез стек?
--
Не можешь достичь желаемого — пожелай достигнутого.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.