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

    Накидал небольшой примерчик, и по нему есть вопрос:

    ExpandedWrap disabled
      #include <iostream>
      #include <functional>
       
      // ──────────────────────────────────────────────────────────────────────────────
       
      using CallbackType = std::function<void(void*)>;
       
      // ──────────────────────────────────────────────────────────────────────────────
       
      class Karbofos {
        
          CallbackType *Begin = nullptr;
          CallbackType *End = nullptr;
        
        public:
        
          const std::string Name = "Карбофос";
          
          void SetCallback(CallbackType *B, CallbackType *E) {
            Begin = B;
            End = E;
          }
          
          void Run() {
            try {
              if (Begin) (*Begin)(this);
              std::cout << "- Не отдам, слон - мой!\n";
              if (End) (*End)(this);
            } catch(const std::bad_function_call& E) {
              std::cout << "Хреновый вызов: " << E.what() << '\n';
            } catch(...) {
              std::cout << "Случилось страшное!\n";
            }
          }
          
      };
       
      // ──────────────────────────────────────────────────────────────────────────────
       
      void Shef(void* i) {
        std::cout << "- Стой, живодер " << ((Karbofos*)(i))->Name << "!\n";
      }
       
      // ──────────────────────────────────────────────────────────────────────────────
       
      void Kollega(void* i) {
        std::cout << "- " << ((Karbofos*)(i))->Name << ", ты немец и контрабандист!\n";
      }
       
      // ──────────────────────────────────────────────────────────────────────────────
       
      int main() {
        Karbofos Object;  
        CallbackType S = Shef;
        CallbackType K = Kollega;
        Object.SetCallback(&S,&K);
        Object.Run();
        return 0;
      }

    Как мне в SetCallback передать сразу указатели на функции, без использования временных переменных?

    Добавлено
    Блин, переработался я :lol: new CallbackType(), решает ... осталось как-то возможную утечку памяти подпилить хитрыми указателями.
      На SO залепили на умных указателях. Ну выход. Ну почему просто так нельзя как-то?
        Цитата JoeUser @
        Как мне в SetCallback передать сразу указатели на функции, без использования временных переменных?

        У тебя прям талант придумывать себе проблемы. Убери указатели вообще у CallbackType. Зачем ты их туда написал? С какой целью ты их туда написал? Сам CallbackType - не является разве указателем(ну вернее он является std::function, но сам шаблонный параметр то указатель на функцию)?
        Ты у себя прилепил указатель на указатель на функцию и спрашиваешь такие вещи.

        https://ideone.com/miVYwD
        ExpandedWrap disabled
              #include <iostream>
              #include <functional>
              
              // ──────────────────────────────────────────────────────────────────────────────
              
              using CallbackType = std::function<void(void*)>;
              
              // ──────────────────────────────────────────────────────────────────────────────
              
              class Karbofos {
              
                  CallbackType Begin = nullptr;
                  CallbackType End = nullptr;
              
                public:
              
                  const std::string Name = "Карбофос";
              
                  void SetCallback(CallbackType B, CallbackType E) {
                    Begin = B;
                    End = E;
                  }
              
                  void Run() {
                    if (Begin) (Begin)(this);
                    std::cout << "- Не отдам, слон - мой!\n";
                    if (End) (End)(this);
                  }
              
              };
              
              // ──────────────────────────────────────────────────────────────────────────────
              
              void Shef(void* i) {
                std::cout << "- Стой, живодер " << ((Karbofos*)(i))->Name << "!\n";
              }
              
              // ──────────────────────────────────────────────────────────────────────────────
              
              void Kollega(void* i) {
                std::cout << "- " << ((Karbofos*)(i))->Name << ", ты немец и контрабандист!\n";
              }
              
              // ──────────────────────────────────────────────────────────────────────────────
              
              int main() {
                Karbofos Object;  
                //CallbackType S = Shef;
                //CallbackType K = Kollega;
                Object.SetCallback(Shef,Kollega);
                Object.Run();
                return 0;
              }


        Добавлено
        Цитата JoeUser @
        На SO залепили на умных указателях. Ну выход. Ну почему просто так нельзя как-то?

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

        Добавлено
        Цитата JoeUser @
        Блин, переработался я :lol: new CallbackType(), решает ... осталось как-то возможную утечку памяти подпилить хитрыми указателями.

        "...Таких извращений Иван не видал!..." © Красная Плесень.
        Сообщение отредактировано: Wound -
          Киля, ну прости! :lol: Спасибо.

          Добавлено
          Кстати, есть еще совет вот такой:
          ExpandedWrap disabled
            void SetCallback(CallbackType B, CallbackType E) {
              Begin = std::move(B);
              End = std::move(E);
            }

          На сколько тут std::move нужен?
            Цитата JoeUser @
            На сколько тут std::move нужен?

            Без понятия, тонкости реализации я уже забыл, это пусть лучше Qraizer просветлит.
            Но как по мне - он там нахрен не нужен.
            Во первых, чтоб применять move - Нужен rvalue, т.е. функция должна принимать что то типа:
            ExpandedWrap disabled
                  void SetCallback(CallbackType&& B, CallbackType&& E) {
                    Begin = std::move(B);
                    End = std::move(E);
                  }

            Во вторых, даже если все будет так - никаких гарантий нет что будет реализовано перемещение.
            В третьих, даже если ты явно не напишешь std::move, а по логике он там применим, компилятор сам выполнит перемещение(соптимизирует и выполнит)
            В четвертых - у тебя там не просто указатели на какие то переменные, а указатели на функцию, не думаю что оно там будет что то перемещать, хотя ньюансы не знаю.

            ИМХО - это лишнее.
              Лан, ждем Qraizer8-)
                Ну и к слову вопрос еще состоит в том - можно ли перемещать указатели? У меня стойкое ощущение что указатель - это lvalue, а никак не rvalue.
                Майерса год-два назад читал, там про это все написано.

                Добавлено
                Как мне помнится
                lvalue - это то, что живет на следующей строчке, после его объявления.
                rvalue - это то, что не живет на следующей строчке, после его объявления.

                Что то типа там:
                ExpandedWrap disabled
                  int a = 5; //! a = lvalue, 5 - rvalue
                  SomeClass b = a.getSomeClass(); //! b - lvalue, a.getSomeClass() - rvalue(если возвращается копия объекта, а не какой нибудь кусок памяти в куче).
                  void SomeFunc(std::string str); //! str - rvalue, потому что живет не дольше SomeFunc
                  void SomeFunc2(const std::string& str)//! str - lvalue, потому что живет дольше SomeFunc

                Это я так по памяти воспроизвел. Значит и указатель на функцию это 100% lvalue, и std::move, просто скопирует побайтно объект, никаких семантик перемещения не будет.

                Добавлено
                Разве что у тебя там std::function сможет переместится, что то я его проглядел, но это уже надо его конструкторы смотреть - если есть перемещающий, возможно и можно.
                Сообщение отредактировано: Wound -
                  Wound, я бегло глянул в сети, не вдавался в подробности. Пишут, что std::move как-то связан со списками захвата, если в качестве функции передается лямбда.

                  И вааще, Киля, ты должен оценить сейчас всю глубину глубин :lol:

                  user posted image
                    Цитата JoeUser @
                    Пишут, что std::move как-то связан со списками захвата, если в качестве функции передается лямбда.

                    Ну тот код который привел ты - у тебя там нет лямбд :-?
                      Цитата Wound @
                      Ну тот код который привел ты - у тебя там нет лямбд

                      За-то я написал "если" :)
                        Цитата JoeUser @
                        За-то я написал "если"

                        Ну сам std::move вообще не занимается ничем, кроме каста входящего значения в rvalue, так что вряд ли он там может быть с чем то связан. Вот например можно посмотреть псевдро-реализацию std::move в блоге Майерса, ну или почитать его книжку, там об этом написано.
                        http://scottmeyers.blogspot.com/2012/11/on...of-stdmove.html
                          Начнём с того, что функциональные объекты придумали как раз для того, чтобы добавить к "фрагменту кода" семантику значений и тем самым сделать работу с ним подобной работе с данными: запомнил, передал, переприсвоил, "частичные запомнил" аргументы, ...использовал запомненное, в смысле, вызвал. Лепить к ним ещё и указатели чаще всего бессмысленно, не реже, чем через поинтеры работать с обычными переменными, что лежат не в dynamic storage.
                          Продолжим тем, что ежели функция принимает неконстанту иначе, нежели по значению, это означает контракт, при котором она будет его менять, т.е. через него возвращается результат её работы. Поэтому Стандарт запрещает передавать rvalue под такие параметры, ибо они, являясь временными объектами, по возврату из функции просто не дают возможности этими результатами воспользоваться, ибо они будут разрушены на ближайшей ; (ну, почти всегда на ближайшей), а значит программист практически наверняка облажался, написав такую конструкцию.
                          Цитата JoeUser @
                          На сколько тут std::move нужен?

                          Цитата Wound @
                          Но как по мне - он там нахрен не нужен.
                          Во первых, чтоб применять move - Нужен rvalue, ...
                          Не спорю, запутаться с семантикой ссылок недолго. Сам путался, пока не привык. Но это несложно, не сложнее, чем разобраться с ссылками после C, где их не было.
                          Вы путаете причину и следствие. Немного ликбеза. std::move() нужен, чтобы ...скажем так, преобразовать (не правильный глагол на самом деле) объект к rvalue ref, изначально таковым не являвшимся. Нужно это конечно же для того, чтобы компилятор в этой точке смог использовать семантику перемещения, если сможет, ибо в противном случае он предпочтёт другие методы. Связано это с тем, что (и снова не вполне правильная терминология) перемещения обладают низким приоритетом при наличии других возможностей. А это в свою очередь связано с тем, что семантика перемещения подразумевает разрушение своего источника, что естественно весьма опасно для невременных объектов, поэтому надёжнее предположить, что "программист практически наверняка облажался, написав такую конструкцию" ©. Используя std::move(), программист чётко даёт понять компилятору, что он не буратина, и знает, что делает. Другой причины использовать std::move() нет. В частности его бессмысленно применять к объектам, которые и так уже rvalue ref.
                          И тут есть одна ловушка: rvalue ref – это просто контракт, срабатывающий при инициализации, который разрешает биндить ссылки на временные объекты, что иначе запрещено контрактом обычных ссылок по причине, как выше было аргументировано. Но в остальном это самые что ни на есть обычные ссылки, которые, как известно являются псевдонимами своих подссыльних объектов. Разница между этими типами ссылок в том, что обычная lvalue ссылка является псевдонимом lvalue, а rvalue ref псевдонимом rvalue. Это приводит к тому, что после инициализации любое использование lvalue ref сводится к lvalue, что практически не привносит в дальнейшем особых сложностей в семантику использования получившегося в итоге объекта, тогда как использование rvalue ref сводится к rvalue, что в связи с вышеозначенным низким приоритетом бинда rvalue к ссылочной семантике, очень часто приводит к необходимости постоянно повторять компилятору, что мы не буратина.
                          Поэтому, Wound, ты прав в том смысле, что std::move не помешает, чтобы компилятор смог использовать семантику перемещения в присваиваниях Begin и End, но для этого источникам нет необходимости быть обязательно rvalue ref, так что параметры SetCallback() могут быть и обычными значениями. Другое дело, что не объявив их rvalue ref, сам вызов SetCallback() при связывании аргументов с его параметрами не заюзает перемещения, аргументы в параметры скопируются, так что да, имеет смысл идти до конца и их также объявить как rvalue ref. Однако это уже не так однозначно, так как в результате контракт допускает, что при вызове SetCallback() её аргументы могут быть также разрушены в точке инициализации её параметров, а не только эти параметры в присваиваниях Begin и End, тогда как если параметры SetCallback() суть простые значения, подобного с аргументами не произойдёт: параметры, будучи их копиями, могут быть разрушены после перемещения Begin и End, т.к. к rvalue ref будут сведены они, т.е. разрушатся только лишь копии аргументов.
                          Что же касается
                          Цитата Wound @
                          В третьих, даже если ты явно не напишешь std::move, а по логике он там применим, компилятор сам выполнит перемещение(соптимизирует и выполнит)
                          то как я чуть выше сказал, компилятор сам этого не сделает, для него использование rvalue ref порождает новые rvalue объекты, которые сводить обратно к rvalue ref нужно заново. Точнее, иногда он всё-таки будет способен на подобное, но в очень редких случаях, например, если источником уже является некая несводимая rvalue ref, например возвращаемое значение некой функции, которая возвращает результат по rvalue ref.
                          Цитата Wound @
                          Во вторых, даже если все будет так - никаких гарантий нет что будет реализовано перемещение.
                          Ну это классика. Семантика перемещения для стандартных типов не описывает, что происходит с источниками, однако подавляющее большинство реализаций будут просто их копировать, так что никакой разницы от копирования нет. Но это не точно, Стандарт ничего тут не гарантирует, просто реализациям так проще. Что касается перемещений не стандартных типов, то тут всё в руках программиста, написавшего (или забившего на это) код перемещения.

                          Добавлено
                          Вот маленький пример для иллюстрации сказанного
                          ExpandedWrap disabled
                            int b;
                             
                            int&& f(int&& z)
                            {
                              b = std::move(z);             // без std::move() скопилится, но и не разрушит z
                             
                            //  return z;                   не скопилится, нужен каст из rvalue к rvalue ref
                              return std::move(z);
                            }
                             
                            void g(int&& z)
                            {
                              // первый (внутренний) вызов без std::move() не скопилится, нужен каст из rvalue к rvalue ref
                              // второй (внешний) вызов std::move() не требует, т.к. это несводимый контекст использования ссылок
                              f(f(std::move(z)));
                            }
                          Сообщение отредактировано: Qraizer -
                            Qraizer, так в коде:

                            ExpandedWrap disabled
                              void SetCallback(CallbackType B, CallbackType E) {
                                Begin = std::move(B);
                                End = std::move(E);
                              }

                            Все-таки std::move нужен, иначе будут копирования?
                              Угу. Даже если там был бы только перемещающий operator=(), компилятор сам rvalue ref из rvalue не сделает, остановится с ошибкой.

                              Добавлено
                              С другой стороны копирование std::function без захваченных неPOD дешёвое, так что много не потеряешь.
                                Цитата Wound @
                                Во первых, чтоб применять move - Нужен rvalue, т.е. функция должна принимать что то типа:

                                Не обязательно.
                                ExpandedWrap disabled
                                  void MyClass::set_something(std::vector<Something> value)  // Передача по значению
                                  {
                                      this->something = std::move(value); // Переместит, лишних копирований не будет
                                  }


                                Цитата Qraizer @
                                Поэтому Стандарт запрещает передавать rvalue под такие параметры, ибо они, являясь временными объектами, по возврату из функции просто не дают возможности этими результатами воспользоваться, ибо они будут разрушены на ближайшей ; (ну, почти всегда на ближайшей), а значит программист практически наверняка облажался, написав такую конструкцию.

                                По мне так это просто недосмотр языка. По-моему не появится никаких проблем, если разрешить передавать rvalue в параметры-неконстантные ссылки, которых бы не было в случае параметров-константных ссылок.
                                  Пусть будет тут вторая часть истории с хэпиэндом :)

                                  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 -
                                                                Цитата OpenGL @
                                                                Ну да, функция выполняет две задачи, но они вместе могут рассматриваться как одна. Ты видишь в этом какое-либо противоречие?
                                                                Конечно. Иначе можно было бы одной задачей считать любую композицию действий. Твоё право написать функцию, возвращающую минимальное простое число, большее своего аргумента и считать это одной задачей. Но когда ты будешь её реализовывать, наверняка декомпозируешь на несколько более простых. Неужели не будешь при этом их оформлять отдельными функциями и напишешь структурную простыню на пару экранов? Тут хотел ещё дальше написать, но передумал, потому что:
                                                                Цитата OpenGL @
                                                                Если про то, что хотел сделать программист c-style cast-ом, то он с обсуждением не связан.
                                                                Понятно. Не просто связан, а ответ на него является первопричиной данного холивара. Вынужден констатировать, что разговор окончен.
                                                                Сообщение отредактировано: Qraizer -
                                                                  Цитата Qraizer @
                                                                  Иначе можно было бы одной задачей считать любую композицию действий.

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

                                                                  Добавлено
                                                                  Цитата Qraizer @
                                                                  Не просто связан, а ответ на него является первопричиной данного холивара.

                                                                  Не связан. C style casts легко провоцируют ошибки, в отличие от предмета спора. Ну или ты, как обычно, делаешь слишком тонкий намёк :D
                                                                    Цитата OpenGL @
                                                                    Цитата Qraizer @
                                                                    Иначе можно было бы одной задачей считать любую композицию действий.
                                                                    Можно, вопрос лишь в том, имеет это какой-либо смысл или нет.
                                                                    Дальше абзац ты не читал, я понял.
                                                                    Цитата OpenGL @
                                                                    C style casts легко провоцируют ошибки, в отличие от предмета спора.
                                                                    C style casts не провоцирует ошибок. Предмет спора не провоцирует ошибок. Ты явно продемонстрировал, что не в теме.
                                                                    Бинды rvalue на ссылки, вещественные типы и operator<<, operator>> и operator%, новый стиль кастов, отсутствие частичной специализации шаблонов функций, иммутабельность лямбд по умолчанию, невозможность перегрузки некоторых операций и ещё многое другое – всё это растёт из одного корня: философии, положенной в основу языка.
                                                                    OpenGL, я сформулировал принцип, следуя которому язык развивался с начала 80-ых, ты упорно не хочешь его принять. Я задал простой вопрос, ответ на который легко отличает человека, знающего язык, от человека, понимающего язык. Трижды задал. Ты наотрез отказываешься отвечать. Я привёл ещё три примера следования этому же принципу, два из них ты проигнорировал, в третьем не увидел связи с – внезапно – исходным принципом. Я на что-то ещё и намекаю? Серьёзно, OpenGL?
                                                                    Зачем ты продолжаешь писать в тему, которая тебе не интересна? Ок, считай, что я намекаю на то, что для Плюсов ты безнадёден. Ты сюда пришёл меня подоставать в надежде, что сорвусь?
                                                                    Сообщение отредактировано: Qraizer -
                                                                      Цитата Qraizer @
                                                                      Дальше абзац ты не читал, я понял.

                                                                      Ты понял неверно :-? С чего ты вообще это взял? Написанное мной не противоречит этому абзацу дальше.

                                                                      Цитата Qraizer @
                                                                      C style casts не провоцирует ошибок. Предмет спора не провоцирует ошибок. Ты явно продемонстрировал, что не в теме.

                                                                      c style casts-то не провоцирует? :lool:
                                                                      Ладно, ты опять включил режим мара тьфу, мудрого сенсея то есть. Ну тебя нафиг, пожалуй.

                                                                      Добавлено
                                                                      Вообще, кто-нибудь понял, что Qraizer хотел этой своей аналогией со c style casts сказать?

                                                                      Сообщения были разделены в тему "Обслуживание Мас"
                                                                        Я с вопросом к ТС-у.

                                                                        А чего ты хочешь добиться, используя std::move?
                                                                        CallbackType - это ссылка на функцию... технически - указатель.
                                                                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                        0 пользователей:


                                                                        Рейтинг@Mail.ru
                                                                        [ Script execution time: 0,1089 ]   [ 17 queries used ]   [ Generated: 25.04.24, 01:48 GMT ]