На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Избежать копипаста при перегрузке
    Добрый день. Есть функция:
    ExpandedWrap disabled
      void foo(std::function<bool(bla-bla)> f1, std::function<bool(another-bla-bla)> f2)
      {
          // Something1
          if(f1(some1)) return;
          // Something2
          if(f2(some2)) return;
          // Something3
      }

    Иными словами - передаваемые ей аргументы являются условиями, когда надо прекратить выполнение. Захотелось её изменить так, чтобы при передаче параметра типа std::funciton<void(...)> (или соответствующей лямбды) её поведение было эквивалентно случаю, когда этот параметр возвращает false. Можно ли это сделать без написания ещё трёх перегрузок с практически одинаковым телом?
      ExpandedWrap disabled
        void foo()
        {
        }
         
        template <typename... TFunc>
        void foo(std::function<bool(bla-bla)> f1, TFunc&&... funcs)
        {
          if (!f1(......))
             foo(std::forward<TFunc>(funcs)...);
        }


      Добавлено
      Как обычно, не прочитал условие. У меня для случая, чтоб не заморачиваться с возвращаемым результатом сделана вот такая конструкция

      ExpandedWrap disabled
        template <typename _T>
        struct CNoVoidResult
        {
            template <typename T, typename TFunc, typename... TT>
            static auto Call(T &&_void, TFunc &&func, TT&&... args)
            {
                return std::invoke(std::forward<TFunc>(func), std::forward<TT>(args)...);
            }
        };
         
        template <>
        struct CNoVoidResult<void>
        {
            template <typename T, typename TFunc, typename... TT>
            static T Call(T &&_void, TFunc &&func, TT&&... args)
            {
                std::invoke(std::forward<TFunc>(func), std::forward<TT>(args)...);
                return std::forward<T>(_void);
            }
        };
         
        template <typename T, typename TFunc, typename... TT> inline
        auto CallNoVoid(T &&_void, TFunc &&func, TT&&... args)
        {
            typedef decltype(std::invoke(std::forward<TFunc>(func), std::forward<TT>(args)...)) TRes;
            return CNoVoidResult<TRes>::Call(std::forward<T>(_void), std::forward<TFunc>(func), std::forward<TT>(args)...);
        }


      Добавлено
      Используется примерно так
      ExpandedWrap disabled
                bool func1()
                {
                    return true;
                }
                
                void func2()
                {
                }
                
                template <typename TFunc, typename... TFunc>
                void foo(TFunc &&func, TFuncs&&... funcs)
                {
                    if (!CallNoVoid(false, std::forward<TFunc>(func))
                        foo(std::forward<TFuncs>(funcs)...)
                }
                
                foo(func1, func2);
      Сообщение отредактировано: Олег М -
        Хм. Спасибо за идею - я пытался сделать что-то вроде
        ExpandedWrap disabled
          template<class R1, class R2> void foo(std::function<R1(bla-bla1)> f1, std::function<R2(bla-bla2)> f2)
          {
          ...
          }

        и получал ошибку невозможности вывести типы R1 и R2. А просто сделать их шаблонами и через std::result_of вывести типы почему-то не додумался. В итоге сделал как-то так:
        ExpandedWrap disabled
          template<class F, class ... Args> std::enable_if_t<std::is_same<std::result_of_t<F(Args...)>, bool>::value, bool> wrap(F f, Args ... args)
          {
              return f(std::forward<Args>(args)...);
          }
           
          template<class F, class ... Args> std::enable_if_t<!std::is_same<std::result_of_t<F(Args...)>, bool>::value, bool> wrap(F f, Args ... args)
          {
              f(std::forward<Args>(args)...);
              return false;
          }
           
          // Использование
          template<class F1, class F2> void foo(F1 f1, F2 f2)
          {
              std::cout << "One\n";
              if (wrap(f1, 1)) return;
              std::cout << "Two\n";
              if (wrap(f2, 2.0, 3.0)) return;
              std::cout << "Three\n";
          }
          Можно и так. Только разве не так надо делать wrap(F f, Args&&... args), чтоб универсальная ссылка была? По-моему, у тебя копии аргументов будут передаваться.
            Цитата Олег М @
            Только разве не так надо делать wrap(F f, Args&&... args), чтоб универсальная ссылка была?

            Да, так лучше, пожалуй.
            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
            0 пользователей:


            Рейтинг@Mail.ru
            [ Script execution time: 0,0505 ]   [ 16 queries used ]   [ Generated: 28.04.24, 13:39 GMT ]