Почему компилятор не убежден в том, что моя лямбда имеет нужный тип?
blockquote>Функции шаблона, которые будут предложены для вывода их параметров шаблона , не делают преобразования , Лямбда не является указателем на функцию, поэтому нет способа вывести
T
в этот аргумент. Поскольку все аргументы функции независимо выводят свои параметры шаблона (если исключение не заблокировано), это приводит к ошибке.Существует ряд исправлений, которые вы можете сделать.
Вы можете исправить
Predicate predicate
template <class T> int binsearch(const std::vector<T> &ts, bool (*predicate)(T))
Заменить указатель функции на
Predicate predicate
илиPredicate&& predicate
и оставить тело неизменным.template <class T, class Predicate> int binsearch(const std::vector<T> &ts, Predicate&& predicate)
Использовать блокировку вычета:
template<class T>struct tag_t{using type=T;}; template<class T>using block_deduction=typename tag_t<T>::type; template <class T> int binsearch(const std::vector<T> &ts, block_deduction<bool (*)(T)> predicate)
необязательно при замене указателя функции на
std::function<bool(T)>
.Вы можете исправить его на сайте вызова.
Вы можете передать
T
вручнуюbinsearch<T>(vec, [](int x){return x<0;})
.Вы можете разложить лямбда на указатель функции, поставив перед ней
+
+[](int x)
... илиstatic_cast<bool(*)(int)>(
...)
.Лучшим вариантом является
Predicate
. Это также то, что делает стандартный код библиотеки.Мы также можем сделать еще один шаг и сделать ваш код еще более общим:
template <class Range, class Predicate> auto binsearch(const Range &ts, Predicate&& predicate) -> typename std::decay< decltype(*std::begin(ts)) >::type
-> typename std::decay
... trailing return тип type может быть исключен в C ++ 14.. Преимущество этого в том, что если тело также использует
std::begin
иstd::end
для поиска итераторов begin / end,binsearch
теперь поддерживаетdeque
s, плоские массивы C-стиля,std::array
s,std::string
s,std::vector
s и даже некоторые пользовательские типы.
Ваше исходное решение сохраняет 10000 объектов в 10000 транзакциях и создает для него 10000 объектов, поэтому это самый худший возможный подход.
Технически правильным способом должно быть следующее:
public void storeBookings(final List<Booking> bookings) {
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.insertOrUpdate(bookings);
}
});
}
В большинстве случаев, когда сохраненный объект не совпадает с исходным объектом, что я делаю это:
public void storeBookings(final List<Booking> bookings) {
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
RealmBook realmBook = new RealmBook();
for(Booking booking : bookings) {
realmBook = mapper.toRealm(booking, realmBook); // does not create new instance
realm.insertOrUpdate(realmBook);
}
}
});
}
В этом решении используется 1 отдельный объект для сопоставления содержимого списка.
insertOrUpdate()
. Я попытался следовать тому, как они показали в своем примере кода. Я знал, что есть проблема, но вы помогли мне найти лучший подход. Благодарю. – Hesam 8 September 2016 в 17:56