Size: a a a

2021 March 17

AF

Aidar Fattakhov in pro.cxx
Андрей Соловьев
Проверял на clang и gcc
источник

AF

Aidar Fattakhov in pro.cxx
что тут не так?
источник

АС

Андрей Соловьев... in pro.cxx
Aidar Fattakhov
что тут не так?
Это я уже путаюсь с типами в примере - Анатолий по этому поводу возмущался. Вот проблема:
https://godbolt.org/z/GcEhcE
источник

AF

Aidar Fattakhov in pro.cxx
так и в чем проблема?
источник

AF

Aidar Fattakhov in pro.cxx
просто преобразования чисел имеют одинаковую стоимость
источник

O

Ofee in pro.cxx
Андрей Соловьев
Там решений - вагон. Шаблонный конструктор, концепт, просто аргументы местами поменять. Я понять особенность языка не могу. int64_t неявно конвертируется в double, а вот int - почему-то нет. Была здесь идея, что дело в числе преобразований типа, но по мне везде только одно преобразование.
Вам помогает не сама смена аргументов местами, а то, что после их смены, аргументы перестают подходить ко второй перегрузке полностью

Из вашего же примера, для A, x точно подходит по типу для первой перегрузки, а other точно подходит для второй. При этом, для оставшегося аргумента в случае обеих перегрузок требуется преобразование – либо x к int, либо other к int64_t, компилятор не ванга, он не собирается угадывать, какое из этих преобразований более правильно. Я больше скажу – даже два программиста могут не сойтись во мнении

Для B же такой проблемы нет потому что для первой перегрузки требуется только одно преобразование – other в int64_t, а для второй – сразу два, x в int, а other в double, т.е. вторая перегрузка ни в каком виде не может быть более приоритетной, чем первая
источник

АС

Андрей Соловьев... in pro.cxx
Ofee
Вам помогает не сама смена аргументов местами, а то, что после их смены, аргументы перестают подходить ко второй перегрузке полностью

Из вашего же примера, для A, x точно подходит по типу для первой перегрузки, а other точно подходит для второй. При этом, для оставшегося аргумента в случае обеих перегрузок требуется преобразование – либо x к int, либо other к int64_t, компилятор не ванга, он не собирается угадывать, какое из этих преобразований более правильно. Я больше скажу – даже два программиста могут не сойтись во мнении

Для B же такой проблемы нет потому что для первой перегрузки требуется только одно преобразование – other в int64_t, а для второй – сразу два, x в int, а other в double, т.е. вторая перегрузка ни в каком виде не может быть более приоритетной, чем первая
Я, наверное, куда-то не туда смотрю. В примере по ссылке закомментирована строка 20. Именно в ней проблема. При ее вызове тип первого аргумента конструктора совпадает с типом первого аргумента перегрузки. Второй аргумент требует преобразования. Компилятор вместо этого делает перегрузку номер два, где нужно выполнить преобразование типа первого аргумента и второй преобразования не требует.
Вместо преобразования int->int64_t делается преобразование int64_t->double.
Я могу это объяснить только тем, что стандарт не предъявляет требований к очередности обращения к аргументам функции.
источник

АС

Андрей Соловьев... in pro.cxx
И да, компилятор выбирает произвольно.
источник

AE

Andrew Evseev in pro.cxx
Ilia Zviagin
C++ Best Practices (2020)
Автор: Jason Turner
Тут написано avoid std::bind и std::function. Первая давно уже "проклята". А что по поводу второй? В каких-то случаях допускается?
источник

IZ

Ilia Zviagin in pro.cxx
Andrew Evseev
Тут написано avoid std::bind и std::function. Первая давно уже "проклята". А что по поводу второй? В каких-то случаях допускается?
Ну читай, может там написано...
источник

AB

Artöm Bakri Al-Sarmi... in pro.cxx
Andrew Evseev
Тут написано avoid std::bind и std::function. Первая давно уже "проклята". А что по поводу второй? В каких-то случаях допускается?
Для стирания типа
источник

O

Ofee in pro.cxx
Андрей Соловьев
Я, наверное, куда-то не туда смотрю. В примере по ссылке закомментирована строка 20. Именно в ней проблема. При ее вызове тип первого аргумента конструктора совпадает с типом первого аргумента перегрузки. Второй аргумент требует преобразования. Компилятор вместо этого делает перегрузку номер два, где нужно выполнить преобразование типа первого аргумента и второй преобразования не требует.
Вместо преобразования int->int64_t делается преобразование int64_t->double.
Я могу это объяснить только тем, что стандарт не предъявляет требований к очередности обращения к аргументам функции.
Всё верно, тип первого аргумента конструктора совпадает с типом первого аргумента первой перегрузки. А тип второго аргумента конструктора совпадает с типом второго аргумента второй перегрузки

Компилятор не собирается гадать, какое из этих двух совпадений более желанное для пользователя
источник

АС

Андрей Соловьев... in pro.cxx
Ofee
Всё верно, тип первого аргумента конструктора совпадает с типом первого аргумента первой перегрузки. А тип второго аргумента конструктора совпадает с типом второго аргумента второй перегрузки

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

АС

Андрей Соловьев... in pro.cxx
Большое спасибо!
источник

IZ

Ilia Zviagin in pro.cxx
А что плохого в std::function ?
источник

D

Danya in pro.cxx
Andrew Evseev
Тут написано avoid std::bind и std::function. Первая давно уже "проклята". А что по поводу второй? В каких-то случаях допускается?
Когда например предпочитаешь более понятный код перфомансу
источник

AE

Andrew Evseev in pro.cxx
Danya
Когда например предпочитаешь более понятный код перфомансу
Вот это мне близко
источник

AE

Andrew Evseev in pro.cxx
Ilia Zviagin
А что плохого в std::function ?
Из текста в книге я так и не понял
источник

O

Ofee in pro.cxx
Andrew Evseev
Из текста в книге я так и не понял
Автор предлагает заглянуть в Compiler Explorer и сравнить три разных примера кода на предмет скорости компиляции и качества сгенерированного кода. Я же добавил ещё и четвёртый. Могу лишь предположить, что исходный посыл был не "не используйте std::bind и не используйте std::function", а "не используйте std::bind и std::function вместе"

Там сразу видно, что если один лишь std::bind компилятор смог оптимизировать вплоть до вычисления на этапе компиляции (как и лямбду, кстати), а std::function сгенерировал некоторый объем лишнего кода, то их комбинация привела к тому, что компилятор вообще не разобрался, что делать и нагенерировал кучу лишнего

Похожий результат показывает и MSVC, однако Clang справляется со всеми 4 примерами совершенно одинаково
источник

DP

Denis Paukaev in pro.cxx
Ofee
Автор предлагает заглянуть в Compiler Explorer и сравнить три разных примера кода на предмет скорости компиляции и качества сгенерированного кода. Я же добавил ещё и четвёртый. Могу лишь предположить, что исходный посыл был не "не используйте std::bind и не используйте std::function", а "не используйте std::bind и std::function вместе"

Там сразу видно, что если один лишь std::bind компилятор смог оптимизировать вплоть до вычисления на этапе компиляции (как и лямбду, кстати), а std::function сгенерировал некоторый объем лишнего кода, то их комбинация привела к тому, что компилятор вообще не разобрался, что делать и нагенерировал кучу лишнего

Похожий результат показывает и MSVC, однако Clang справляется со всеми 4 примерами совершенно одинаково
Рассчитывать на то что компилятор сгенерирует довольно наивно ) проще использовать std::function только там, где без него не обойтись (type erase?), а вместо бинд есть лямбды, ну и те 2 кейса в год, когда нужен бинд (уже даже не помню какие)
источник