На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (3) 1 [2] 3  все  ( Перейти к последнему сообщению )  
> Можно ли как-то без временных переменных?
    Пусть будет тут вторая часть истории с хэпиэндом :)

    ExpandedWrap disabled
      #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;
      }
      Цитата OpenGL @
      По-моему не появится никаких проблем, если разрешить передавать rvalue в параметры-неконстантные ссылки, которых бы не было в случае параметров-константных ссылок.
      Когда-то в бородатых 90-ых так и было. Можно было по неконстантной ссылке, например в int&, передавать результаты выражений типа a+b. Компилеры писали варнинг, мол, будет заюзана временная переменная, но код генерить это им не мешало. В итоге в C++98 это отменили, ибо это отвращает программеров писать правильные контракты в прототипах функций. Мол, const означает не изменение функцией, его отсутствие означает выходной параметр. А так как временные объекты в качестве выходных параметров использовать невозможно, то вызывающая сторона явно что-то мутит и не знает, что творит.

      Добавлено
      Цитата JoeUser @
      Пусть будет тут вторая часть истории с хэпиэндом
      Ух ты. Кто-то ещё пользует бинды...
        Цитата Qraizer @
        А так как временные объекты в качестве выходных параметров использовать невозможно, то вызывающая сторона явно что-то мутит и не знает, что творит.

        Вот именно с этим я и не согласен. Ну не нужен мне выходной параметр, их 3, но мне в данном случае достаточно одного - так редко это бывает? Более того, МСный компилятор это разрешает, и я что-то не припомню у себя багов, которые бы возникали из-за такого поведения. Просто по мне так если уж запрещать, то и для констант тоже для единообразия, либо разрешать для всего. И что это способствует ненаписанию конрактов я тоже не очень понимаю. Как именно способствует? Ты о том, что вместо const int & они могли объявить параметр как int&? Ну так это программист плохой, пусть учится, да и проставить const где надо это, прямо скажем, не квантовая теория поля, и делается на автомате.
          Цитата OpenGL @
          Ну не нужен мне выходной параметр, их 3, но мне в данном случае достаточно одного - так редко это бывает?
          Это когда функция вызывается, чтобы сделать работу, а тебе не нужен результат? Редко. Чаще бывает, что функция делает много разных работ, а тебе нужны не все, но это тоже плохой дизайн, правда, уже не твой, а автора той функции. Ещё во времена около C++98, а уж в доC++03 так подавно, сложились критерии отказоустойчивого кода, и декомпозиция, сведённая к нескольким задачам в одной интерфейсной единице, в эти критерии никак не укладывается. Почему, думаешь, положить в std::stack элемент можно одним методом, а выдёргивать оттуда двумя? Сначала получи значение с вершины, и потом отдельно удали из std::stack.
          Сообщение отредактировано: Qraizer -
            А ещё, полагаю, с этим тесно связано следующее

            ExpandedWrap disabled
              std::string get_string();
               
              const std::string &x = get_string(); // Ok, string is alive
              std::string &y = get_string(); // Compiler error

            что тоже не добавляет логичности и последовательности системе типов. Имхо, это всё должно либо не компилиться, либо падать при попытке доступа к мёртвому объекту.
              Цитата OpenGL @
              Ну так это программист плохой, пусть учится, да и проставить const где надо это, прямо скажем, не квантовая теория поля, и делается на автомате.
              Вот именно. Но когда на неконстантные ссылки биндятся rvalue, непонятно, то ли автор дурак, что хреново прописал контракт, то ли у тебя лыжи не едут, и ты тупо что-то не понимаешь в используемом тобою API. А так язык внятно говорит, что альтернативы нет.
              По подобной причине C-стайл тайпкастов не в моде. Вот ты можешь сказать, что тут хотел написать программер?
              ExpandedWrap disabled
                void f(const unsigned long *param)
                {
                /* ... */
                  unsigned int *ptr = (unsigned int*)param;
                /* ... */
                }
              Если что, у меня три варианта.
                Цитата Qraizer @
                Это когда функция вызывается, чтобы сделать работу, а тебе не нужен результат? Редко.

                Не обязательно. Параметр, передаваемый по ссылке, может быть одновременно и входным, и выходным параметром. Например, пусть это будет функция, которая как-то перефигачивает входной вектор и попутно записывает его в файл. Меня может интересовать запись в файл, но перефигаченный вот тут в месте вызова мне вообще не нужен, я просто хочу его записать в файл так, как его записывает эта функция.
                  Цитата OpenGL @
                  А ещё, полагаю, с этим тесно связано следующее

                  ExpandedWrap disabled
                    std::string get_string();
                     
                    const std::string &x = get_string(); // Ok, string is alive
                    std::string &y = get_string(); // Compiler error

                  что тоже не добавляет логичности и последовательности системе типов.

                  Это как раз продолжение этой же темы с временными объектами. Функция тебе вернула временный объект, который вскоре будет убит. Однако нередко нужно его использовать неоднократно, поэтому без продления его времени жизни пришлось бы копировать. (Нынче можно ещё переместить, впрочем, что в большинстве случаев решит проблему.) Но без const ты мог бы непреднамеренно, например отдав в другую функцию по неконстантной ссылке, его поменять. Тебе было бы приятно узнать, что между двумя использованиями он внезапно изменился?
                    Цитата Qraizer @
                    По подобной причине C-стайл тайпкастов не в моде. Вот ты можешь сказать, что тут хотел написать программер?

                    Не знаю, я C style casts указателей избегаю не из-за const, а в первую очередь из-за того, что они в конце-концов сведутся к reinterpret_cast-у.
                      Цитата OpenGL @
                      Например, пусть это будет функция, которая как-то перефигачивает входной вектор и попутно записывает его в файл. Меня может интересовать запись в файл, но перефигаченный вот тут в месте вызова мне вообще не нужен, я просто хочу его записать в файл так, как его записывает эта функция.
                      Функция выполняет две задачи. Что ты мне хочешь этим доказать? Что она хреново спроектирована? Это я тебе и так скажу.

                      Добавлено
                      Цитата OpenGL @
                      Не знаю, я C style casts указателей избегаю не из-за const, а в первую очередь из-за того, что они в конце-концов сведутся к reinterpret_cast-у.
                      А какая разница, что сделает компилятор? Мы знаем, что он сделает, но вопрос звучал "что хотел сделать программист".
                      Сообщение отредактировано: Qraizer -
                        Цитата Qraizer @
                        Это как раз продолжение этой же темы с временными объектами. Функция тебе вернула временный объект, который вскоре будет убит. Однако нередко нужно его использовать неоднократно, поэтому без продления его времени жизни пришлось бы копировать.

                        Да, это интересная мысль. При наличии перемещения это особо бесполезно, но заре плюсов вполне могло быть аргументом. Обдумать надо :)
                          Цитата Qraizer @
                          Ух ты. Кто-то ещё пользует бинды...

                          Так нужно:

                          ExpandedWrap disabled
                            K.SetCallback([](void* c, int a, int b){((Shef*)c)->Entreaty(c,a,b);});


                          ???

                          Работает так же, но кажется что тут что-то не так :-?


                          И так работает:

                          ExpandedWrap disabled
                            K.SetCallback([&](void* c, int a, int b){S.Entreaty(c,a,b);});


                          std::bind мне кажется тут понятнее,потому как явно указывает на метод класса, безотностительно наличия переменных этого класса.

                          Че делать-та??? :wacko:
                          Сообщение отредактировано: JoeUser -
                            Цитата Qraizer @
                            Функция выполняет две задачи. Что ты мне хочешь этим доказать? Что она хреново спроектирована? Это я тебе и так скажу.

                            Она выполняет одну задачу.

                            Ну и да, аргумент про продление времени жизни объекта при его присваивании в константную ссылку мне видится несостоятельным. Ты это обосновывал вот так
                            Цитата Qraizer @
                            Функция тебе вернула временный объект, который вскоре будет убит. Однако нередко нужно его использовать неоднократно, поэтому без продления его времени жизни пришлось бы копировать.

                            но это объяснение константность не использует. Точно так же я могу сказать "однако нередко нужно его использовать неоднократно и как-то менять". Не поменялось по-моему ровным счётом ничего. Да, ты дальше пишешь "Но без const ты мог бы непреднамеренно, например отдав в другую функцию по неконстантной ссылке, его поменять. ", но это обоснование того, зачем тебе в этом месте нужна константа, а я говорю о причинах, зачем делать такое исключение для константы и только для неё.
                              Цитата OpenGL @
                              Она выполняет одну задачу.
                              Почему ты противоречишь себе?
                              Цитата OpenGL @
                              Точно так же я могу сказать "однако нередко нужно его использовать неоднократно и как-то менять".
                              Не чаще, чем не интересоваться возвращённым в rvalue результатом. P.S. Иногда мне нужно делить или умножать вещественные на степени двойки.

                              Добавлено
                              P.P.S. Если тебе нужно что-то странное, скажи об этом явно. Сделай переменную, инициализируй своим выражением и передавай агрументом в ссылку. И не интересуйся её дальнейшей судьбой на здоровье. Это ровно то, что ты хочешь, чтобы компилятор сделал за тебя. Компилятору нетрудно сделать это за тебя. Ему также нетрудно сдвигать вещественные или возвращать тебе результат % нам ними. Ему много что нетрудно.
                              Вопрос заключается в том, окупится ли профит от такого дружелюбия дебагом в нередких случаях. Чем раньше ты узнаешь о потенциальных проблемах в коде, тем быстрее и дешевле ты с ними разберёшься. Очень хорошо, когда компилятор понимает твои намерения, а не просто генерит объектный по указке. С вопросом выше ты так и не разобрался?
                                Цитата Qraizer @
                                Почему ты противоречишь себе?

                                Я не противоречу. Ну да, функция выполняет две задачи, но они вместе могут рассматриваться как одна. Ты видишь в этом какое-либо противоречие?
                                Возможно, мы просто о разных функциях говорим. Если ты о публичных методах класса/модуля, то да, я бы скорей всего не стал эту функцию выносить туда. Как деталь реализации такая функция более чем имеет право на существование.

                                Цитата Qraizer @
                                Не чаще, чем не интересоваться возвращённым в rvalue результатом.

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

                                Цитата Qraizer @
                                Сделай переменную, инициализируй своим выражением и передавай агрументом в ссылку.

                                Да это понятно. Неудобно, что на ровном месте компилятор требует бесполезных действий, причём в точно таком же случае, но без константы, он их почему-то не требует. И это несмотря на mutable :D

                                Цитата Qraizer @
                                Вопрос заключается в том, окупится ли профит от такого дружелюбия дебагом в нередких случаях.

                                Мне кажется, что ты переоцениваешь полезность этой фичи. Я, например, с этим сталкивался только когда пытался откомпилить валидный с т.з. майкрософта код на ином компиляторе. Багов же из-за этого я не ловил.

                                Цитата Qraizer @
                                С вопросом выше ты так и не разобрался?

                                Ты про какой вопрос? Если про то, что хотел сделать программист c-style cast-ом, то он с обсуждением не связан.
                                Сообщение отредактировано: OpenGL -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) 1 [2] 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0584 ]   [ 17 queries used ]   [ Generated: 26.04.24, 18:16 GMT ]