Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.217.60.35] |
|
Страницы: (3) 1 [2] 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Пусть будет тут вторая часть истории с хэпиэндом
#include <utility> #include <iostream> #include <functional> //────────────────────────────────────────────────────────────────────────────── using CallbackType = std::function<void(void*, int, int)>; // ────────────────────────────────────────────────────────────────────────────── class Karbofos { CallbackType Call; public: const std::string Name = "Карбофос"; void SetCallback(CallbackType C) { Call = std::move(C); } void Run() { if (Call) Call(this, 1, 20); std::cout << "- Не продам!\n"; } }; //────────────────────────────────────────────────────────────────────────────── class Shef { public: void Entreaty(void* c, int a, int b) { std::cout << "- " << ((Karbofos*)c)->Name << ", продай слона за " << a << "." << b << "р ?\n"; } }; //────────────────────────────────────────────────────────────────────────────── int main() { Karbofos K; Shef S; K.SetCallback(std::bind( &Shef::Entreaty, &S, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3) ); K.Run(); return 0; } |
Сообщ.
#17
,
|
|
|
Цитата OpenGL @ Когда-то в бородатых 90-ых так и было. Можно было по неконстантной ссылке, например в int&, передавать результаты выражений типа a+b. Компилеры писали варнинг, мол, будет заюзана временная переменная, но код генерить это им не мешало. В итоге в C++98 это отменили, ибо это отвращает программеров писать правильные контракты в прототипах функций. Мол, const означает не изменение функцией, его отсутствие означает выходной параметр. А так как временные объекты в качестве выходных параметров использовать невозможно, то вызывающая сторона явно что-то мутит и не знает, что творит. По-моему не появится никаких проблем, если разрешить передавать rvalue в параметры-неконстантные ссылки, которых бы не было в случае параметров-константных ссылок. Добавлено Цитата JoeUser @ Ух ты. Кто-то ещё пользует бинды... Пусть будет тут вторая часть истории с хэпиэндом |
Сообщ.
#18
,
|
|
|
Цитата Qraizer @ А так как временные объекты в качестве выходных параметров использовать невозможно, то вызывающая сторона явно что-то мутит и не знает, что творит. Вот именно с этим я и не согласен. Ну не нужен мне выходной параметр, их 3, но мне в данном случае достаточно одного - так редко это бывает? Более того, МСный компилятор это разрешает, и я что-то не припомню у себя багов, которые бы возникали из-за такого поведения. Просто по мне так если уж запрещать, то и для констант тоже для единообразия, либо разрешать для всего. И что это способствует ненаписанию конрактов я тоже не очень понимаю. Как именно способствует? Ты о том, что вместо const int & они могли объявить параметр как int&? Ну так это программист плохой, пусть учится, да и проставить const где надо это, прямо скажем, не квантовая теория поля, и делается на автомате. |
Сообщ.
#19
,
|
|
|
Цитата OpenGL @ Это когда функция вызывается, чтобы сделать работу, а тебе не нужен результат? Редко. Чаще бывает, что функция делает много разных работ, а тебе нужны не все, но это тоже плохой дизайн, правда, уже не твой, а автора той функции. Ещё во времена около C++98, а уж в доC++03 так подавно, сложились критерии отказоустойчивого кода, и декомпозиция, сведённая к нескольким задачам в одной интерфейсной единице, в эти критерии никак не укладывается. Почему, думаешь, положить в std::stack элемент можно одним методом, а выдёргивать оттуда двумя? Сначала получи значение с вершины, и потом отдельно удали из std::stack. Ну не нужен мне выходной параметр, их 3, но мне в данном случае достаточно одного - так редко это бывает? |
Сообщ.
#20
,
|
|
|
А ещё, полагаю, с этим тесно связано следующее
std::string get_string(); const std::string &x = get_string(); // Ok, string is alive std::string &y = get_string(); // Compiler error что тоже не добавляет логичности и последовательности системе типов. Имхо, это всё должно либо не компилиться, либо падать при попытке доступа к мёртвому объекту. |
Сообщ.
#21
,
|
|
|
Цитата OpenGL @ Вот именно. Но когда на неконстантные ссылки биндятся rvalue, непонятно, то ли автор дурак, что хреново прописал контракт, то ли у тебя лыжи не едут, и ты тупо что-то не понимаешь в используемом тобою API. А так язык внятно говорит, что альтернативы нет.Ну так это программист плохой, пусть учится, да и проставить const где надо это, прямо скажем, не квантовая теория поля, и делается на автомате. По подобной причине C-стайл тайпкастов не в моде. Вот ты можешь сказать, что тут хотел написать программер? void f(const unsigned long *param) { /* ... */ unsigned int *ptr = (unsigned int*)param; /* ... */ } |
Сообщ.
#22
,
|
|
|
Цитата Qraizer @ Это когда функция вызывается, чтобы сделать работу, а тебе не нужен результат? Редко. Не обязательно. Параметр, передаваемый по ссылке, может быть одновременно и входным, и выходным параметром. Например, пусть это будет функция, которая как-то перефигачивает входной вектор и попутно записывает его в файл. Меня может интересовать запись в файл, но перефигаченный вот тут в месте вызова мне вообще не нужен, я просто хочу его записать в файл так, как его записывает эта функция. |
Сообщ.
#23
,
|
|
|
Цитата OpenGL @ А ещё, полагаю, с этим тесно связано следующее std::string get_string(); const std::string &x = get_string(); // Ok, string is alive std::string &y = get_string(); // Compiler error что тоже не добавляет логичности и последовательности системе типов. Это как раз продолжение этой же темы с временными объектами. Функция тебе вернула временный объект, который вскоре будет убит. Однако нередко нужно его использовать неоднократно, поэтому без продления его времени жизни пришлось бы копировать. (Нынче можно ещё переместить, впрочем, что в большинстве случаев решит проблему.) Но без const ты мог бы непреднамеренно, например отдав в другую функцию по неконстантной ссылке, его поменять. Тебе было бы приятно узнать, что между двумя использованиями он внезапно изменился? |
Сообщ.
#24
,
|
|
|
Цитата Qraizer @ По подобной причине C-стайл тайпкастов не в моде. Вот ты можешь сказать, что тут хотел написать программер? Не знаю, я C style casts указателей избегаю не из-за const, а в первую очередь из-за того, что они в конце-концов сведутся к reinterpret_cast-у. |
Сообщ.
#25
,
|
|
|
Цитата OpenGL @ Функция выполняет две задачи. Что ты мне хочешь этим доказать? Что она хреново спроектирована? Это я тебе и так скажу. Например, пусть это будет функция, которая как-то перефигачивает входной вектор и попутно записывает его в файл. Меня может интересовать запись в файл, но перефигаченный вот тут в месте вызова мне вообще не нужен, я просто хочу его записать в файл так, как его записывает эта функция. Добавлено Цитата OpenGL @ А какая разница, что сделает компилятор? Мы знаем, что он сделает, но вопрос звучал "что хотел сделать программист". Не знаю, я C style casts указателей избегаю не из-за const, а в первую очередь из-за того, что они в конце-концов сведутся к reinterpret_cast-у. |
Сообщ.
#26
,
|
|
|
Цитата Qraizer @ Это как раз продолжение этой же темы с временными объектами. Функция тебе вернула временный объект, который вскоре будет убит. Однако нередко нужно его использовать неоднократно, поэтому без продления его времени жизни пришлось бы копировать. Да, это интересная мысль. При наличии перемещения это особо бесполезно, но заре плюсов вполне могло быть аргументом. Обдумать надо |
Сообщ.
#27
,
|
|
|
Цитата Qraizer @ Ух ты. Кто-то ещё пользует бинды... K.SetCallback([](void* c, int a, int b){((Shef*)c)->Entreaty(c,a,b);}); ??? Работает так же, но кажется что тут что-то не так K.SetCallback([&](void* c, int a, int b){S.Entreaty(c,a,b);}); std::bind мне кажется тут понятнее, |
Сообщ.
#28
,
|
|
|
Цитата Qraizer @ Функция выполняет две задачи. Что ты мне хочешь этим доказать? Что она хреново спроектирована? Это я тебе и так скажу. Она выполняет одну задачу. Ну и да, аргумент про продление времени жизни объекта при его присваивании в константную ссылку мне видится несостоятельным. Ты это обосновывал вот так Цитата Qraizer @ Функция тебе вернула временный объект, который вскоре будет убит. Однако нередко нужно его использовать неоднократно, поэтому без продления его времени жизни пришлось бы копировать. но это объяснение константность не использует. Точно так же я могу сказать "однако нередко нужно его использовать неоднократно и как-то менять". Не поменялось по-моему ровным счётом ничего. Да, ты дальше пишешь "Но без const ты мог бы непреднамеренно, например отдав в другую функцию по неконстантной ссылке, его поменять. ", но это обоснование того, зачем тебе в этом месте нужна константа, а я говорю о причинах, зачем делать такое исключение для константы и только для неё. |
Сообщ.
#29
,
|
|
|
Цитата OpenGL @ Почему ты противоречишь себе?Она выполняет одну задачу. Цитата OpenGL @ Не чаще, чем не интересоваться возвращённым в rvalue результатом. P.S. Иногда мне нужно делить или умножать вещественные на степени двойки. Точно так же я могу сказать "однако нередко нужно его использовать неоднократно и как-то менять". Добавлено P.P.S. Если тебе нужно что-то странное, скажи об этом явно. Сделай переменную, инициализируй своим выражением и передавай агрументом в ссылку. И не интересуйся её дальнейшей судьбой на здоровье. Это ровно то, что ты хочешь, чтобы компилятор сделал за тебя. Компилятору нетрудно сделать это за тебя. Ему также нетрудно сдвигать вещественные или возвращать тебе результат % нам ними. Ему много что нетрудно. Вопрос заключается в том, окупится ли профит от такого дружелюбия дебагом в нередких случаях. Чем раньше ты узнаешь о потенциальных проблемах в коде, тем быстрее и дешевле ты с ними разберёшься. Очень хорошо, когда компилятор понимает твои намерения, а не просто генерит объектный по указке. С вопросом выше ты так и не разобрался? |
Сообщ.
#30
,
|
|
|
Цитата Qraizer @ Почему ты противоречишь себе? Я не противоречу. Ну да, функция выполняет две задачи, но они вместе могут рассматриваться как одна. Ты видишь в этом какое-либо противоречие? Возможно, мы просто о разных функциях говорим. Если ты о публичных методах класса/модуля, то да, я бы скорей всего не стал эту функцию выносить туда. Как деталь реализации такая функция более чем имеет право на существование. Цитата Qraizer @ Не чаще, чем не интересоваться возвращённым в rvalue результатом. И это достаточно часто случается, если у тебя основное назначение функции не обработка переданных аргументов, а сайд-эффекты. Допустим, есть функция update_something, которая обновляет в базе некоторые записи по какому-то условию, и возвращает список ключей тех записей, которые были обновлены. Меня запросто в каком-то месте может интересовать только факт того, что обновление завершилось (не было брошено исключение, например), а сам список итоговых записей нафиг не нужен. Цитата Qraizer @ Сделай переменную, инициализируй своим выражением и передавай агрументом в ссылку. Да это понятно. Неудобно, что на ровном месте компилятор требует бесполезных действий, причём в точно таком же случае, но без константы, он их почему-то не требует. И это несмотря на mutable Цитата Qraizer @ Вопрос заключается в том, окупится ли профит от такого дружелюбия дебагом в нередких случаях. Мне кажется, что ты переоцениваешь полезность этой фичи. Я, например, с этим сталкивался только когда пытался откомпилить валидный с т.з. майкрософта код на ином компиляторе. Багов же из-за этого я не ловил. Цитата Qraizer @ С вопросом выше ты так и не разобрался? Ты про какой вопрос? Если про то, что хотел сделать программист c-style cast-ом, то он с обсуждением не связан. |