Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.219.63.90] |
|
Сообщ.
#1
,
|
|
|
Добрый день. Есть функция:
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. Можно ли это сделать без написания ещё трёх перегрузок с практически одинаковым телом? |
Сообщ.
#2
,
|
|
|
void foo() { } template <typename... TFunc> void foo(std::function<bool(bla-bla)> f1, TFunc&&... funcs) { if (!f1(......)) foo(std::forward<TFunc>(funcs)...); } Добавлено Как обычно, не прочитал условие. У меня для случая, чтоб не заморачиваться с возвращаемым результатом сделана вот такая конструкция 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)...); } Добавлено Используется примерно так 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); |
Сообщ.
#3
,
|
|
|
Хм. Спасибо за идею - я пытался сделать что-то вроде
template<class R1, class R2> void foo(std::function<R1(bla-bla1)> f1, std::function<R2(bla-bla2)> f2) { ... } и получал ошибку невозможности вывести типы R1 и R2. А просто сделать их шаблонами и через std::result_of вывести типы почему-то не додумался. В итоге сделал как-то так: 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"; } |
Сообщ.
#4
,
|
|
|
Можно и так. Только разве не так надо делать wrap(F f, Args&&... args), чтоб универсальная ссылка была? По-моему, у тебя копии аргументов будут передаваться.
|
Сообщ.
#5
,
|
|
|
Цитата Олег М @ Только разве не так надо делать wrap(F f, Args&&... args), чтоб универсальная ссылка была? Да, так лучше, пожалуй. |