Один подход, который работает практически из любого места, в том числе из мест, где у вас нет Activity
или View
, заключается в том, чтобы захватить Handler
в основной поток и показать тост:
public void toast(final Context context, final String text) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
Toast.makeText(context, text, Toast.DURATION_LONG).show();
}
});
}
Преимуществом этого подхода является то, что он работает с любыми Context
, включая Service
и Application
.
Стефан Т. Лававей объясняет, почему это не работает в этом видео . В основном проблема заключается в том, что компилятор пытается вывести BaseT
из как параметр std::vector
, так и std::function
. Лямбдой в C ++ является , а не типа std::function
, это неназванный, уникальный неединичный тип, который можно конвертировать в указатель функции, если у него нет списка захвата (empty []
) , С другой стороны, объект std::function
может быть создан из любого возможного типа вызываемого объекта (указатели функций, указатели функций-функций, объекты функций).
Обратите внимание, что я лично не понимаю, почему вы хотите ограничить входящие функторы этой специфической сигнатурой (в дополнение к тому факту, что косвенность через оболочку полиморфной функции, например std::function
, намного более неэффективна, чем прямой вызов функтора (который может даже быть встроенным)), но вот рабочая версия. В принципе, он отключает дедукцию аргумента на части std::function
и выводит BaseT
из аргумента std::vector
:
template<class T>
struct Identity{
typedef T type;
};
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
typename Identity<function<bool (const BaseT &)>>::type func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Другим возможным способом было бы не ограничивать тип функтора напрямую, а косвенно через SFINAE:
template<class T, class F>
auto f(std::vector<T> v, F fun)
-> decltype(bool(fun(v[0])), void())
{
// ...
}
Эта функция будет удалена из набора перегрузки, если fun
не принимает аргумент типа T&
или если тип возврата не конвертируется в bool
. , void()
делает тип возврата f
void
.
Как было показано другими плакатами, это вычет аргумента шаблона для std :: function.
Один интуитивно понятный способ сделать второй фрагмент кода - добавить базовый тип при вызове шаблона функция: findMatches<int>
.
Другой способ, не упомянутый Xeo, используется std :: is_convertible:
template<typename BaseT, typename FUNC>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
static_assert(std::is_convertible<FUNC, function<bool (const BaseT &)> >::value, "func must be convertible to ...");
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Он избегает обертывания lamda в std :: function и обеспечивает сообщение об ошибке.