Кресты / Говнокод #23241 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
CoolIntf::GetInstance().DoSomething();
CoolIntf::GetInstance().DoSomethingElse();
CoolIntf::GetInstance().DoAnything()

для случая когда GetInstance() не инлайнится, кто-нибудь в крестах какое решение (без ручного введения временной переменной) для такого кода придумал?
единственное что нашел это вот это: https://stackoverflow.com/a/2279253 .
потому что "with" слишком общее слово которое в ж не гуглится.

Запостил: Dummy00001 Dummy00001, (Updated )

Комментарии (38) RSS

  • а возвращение инстанса достаточно дорогая операция чтобы настловать мозг?
    Ответить
    • из встроенщины. и дорого (потому что все железо убогое и тормозное), и вызов занимает 4-8 байт.

      первый вызов нужен, но последующие хочется как то убрать.
      Ответить
      • А что плохого в ручном введении переменной? Вроде не так много писанины добавляет.
        auto& p = CoolIntf::GetInstance();
        p.DoSomething();
        p.DoSomethingElse();
        p.DoAnything();
        Ответить
        • > А что плохого [...]

          (1) там еще авто нету.
          (2) ничего, но я хочу что бы это `p` было в какой scope загнано.

          я пробовал извраты на тему `for (auto& p = Aaa::GetInst(); ; ) { /* body */'; break; }`. но там было Нное количество мелких граблей (наброски в офисе - так не вспомню).

          главное: это очень мелкая проблема что бы для неё код перерасхерачивать.
          Ответить
          • Так в плюсах же вроде можно делать scope просто составным оператором?
            do_stuff();
            {
              CoolIntf& I = CoolIntf::GetInstance();
              I.DoSomething();
              I.DoSomethingElse();
              //Здесь I выйдет из скопа и отработает деструктор ~CoolIntf(), если есть.
            }
            do_more_stuff();
            Ответить
            • да. но, повторюсь: это очень мелкая проблема что бы для неё код перерасхерачивать.

              то что я в офисе пытался делать, набросок:
              #include <stdio.h>
              
              #define WITH1(oo)	for (oo, bool xxx = true; xxx; xxx = false)
              
              struct Tt {
              	static Tt tt;
              	static Tt& GetInst() { return tt; };
              	void important_stuff() {
              		printf("Hello World\n");
              	};
              };
              
              int main()
              {
              	auto x = Tt::GetInst();
              	x.important_stuff();
              
              	WITH1( auto t = Tt::GetInst() ) {
              		t.important_stuff();
              	}
              }


              но как выяснилось, в `for()` нельзя переменные разных типов объявлять.
              Ответить
              • Ну ок. Хотя стоит сначала посмотреть, не оптимизирует ли компилятор это дело?
                Ответить
                • нет, не оптимизирует. компилятор не имеет права менять количество вызовов функций. может быть только если он "видит" реализацию, и знает что нет побочных эффектов. но к сожалению эти GetInstance() лежат в .cpp и шансов мало это поменять. хотя ради эксперимента стоит попробовать положить их в .hpp и посмотреть какой эффект это будет иметь.
                  Ответить
              • Чем использование составного оператора отличается от твоего фора?
                Ответить
                • > составного оператора

                  по не-русски?

                  я на просто пытался прикрутить типичный `with` других языков к крестам.
                  Ответить
            • > //Здесь I выйдет из скопа и отработает деструктор ~CoolIntf(), если есть.

              Какой ещё деструктор, там же ссылка, тем более неконстантная.
              Ответить
          • if  (auto&p = Aaa::GetInstance()) {
                p.DoSomething();
                p.DoSomethingElse();
            }
            З.Ы. Хотя if странно смотрится, да.
            Ответить
              • #define WITH(var, expr) if (auto* var = &(expr))
                
                WITH(p, Aaa::GetInstance()) {
                    p->DoSomething();
                    p->DoSomethingElse();
                }
                
                Ответить
                • да, твое первое криво (референс vs bool). но второй вариант уже намного лучше. как по мне, даже и без WITH() дефайна ОК.

                  ЗЫ жаль что к моему текущему проекту не применимо, т.к. на референсах все. указатели всегда надо проверять и кидать ошибку если нулл.

                  ЗЗЫ а вот такое редиско-компилер не съедает (что с авто, что с конкретным типом):
                  if ((Tt& t = (Tt::GetInst()), true)) {
                     printf( "%d\n", t.answer() );
                  }
                  Ответить
                  • template <typename T>
                    struct WithHelper : public T {
                        operator bool() { return true; }
                    };
                    
                    template <typename T>
                    WithHelper<T>& MakeWithHelper(T& ref) {
                        return static_cast<WithHelper<T>&>(ref);
                    }
                    
                    #define WITH(var, expr) if (auto& var = MakeWithHelper(expr))
                    
                    WITH(p, Aaa::GetInstance()) {
                        p.DoSomething();
                        p.DoSomethingElse();
                    }
                    
                    Ответить
                    • а это свежая идея!

                      в конце конечно изврат получается, но принцип интересный.

                      я еще попытался просто оператор сравнения перекрыть и с дамми классом сравнивать (вместо простой бул конверсии) но чего то мой гцц это отказывается в if'е переваривать (`(auto& x = WithHelper(Aaa::GetInstance())) == WithCompareDummy()`).
                      Ответить
                      • Включай C++17, там тебе сделал решение
                        if (Aaa& p = Aaa::GetInstance(); true) {
                          p.DoSomething();
                          p.DoSomethingElse();
                        }
                        Ответить
                        • IAR понадобилось 6 (шесть) лет что бы С++11 сделать. С++17 я думаю что еще столько же лет придётся ждать. и потом еще столько же ждать пока это до проектов дотечёт...

                          что есть весьма обидно, потому что много фич как раз для встроенщины полезны (энумы, конст-экспр).
                          Ответить
                    • А почему статик каст, а не реинтерпред?

                      Или он для обратного преобразования?
                      Ответить
                            • Статик каст тут уместен, он по сути конструктор враппера вызывает. Вообще все преобразования потомок <-> родитель нужно выполнять либо через static_cast, либо через dynamic_cast. Они правильно подсчитают смещения объектов в родительских объектах.
                              А reinterpret нужен, чтобы сказать "будем считать, что в этих байтах лежит что-то другое", без всякого подсчёта смещений.
                              Ответить
                              • Там каст ссылки в ссылку, он не создает новый объект. Да и нет у WithHelper конструктора из базового класса.
                                Ответить
                                • Ты прав, я ерунду сморозил. Враппер никогда не создаётся, тут мы просто компилятор делаем счастливым. У ссылки меняется только тип, поскольку T это первый объект во враппере и имеет тот же адрес.
                                  Ответить
    • только с войд методами работает. которые все нужно конвертить.
      Ответить
    • да.

      но в данном конкретном проекте там стоит проверка (и обработка) ошибки доступа к глобальным объектам до того как инициализация оного завершилась. сама проверка - один глупый if. а вот вход в обработчик фатальных ошибок - толстый.
      Ответить

Добавить комментарий

Помни, guest, за тобой могут следить!

    А не использовать ли нам bbcode?


    8