2016-04-13 5 views
0

Я получил this example о реализации обобщенной memoization в C++. Однако, поскольку кто-то сделал уведомление в комментарии this, исходный код делает 2 поиска, а код ниже составляет только один.Код памятки в C++: почему он не работает?

Единственная проблема в том, что на втором return есть ошибка, которую я не понимаю.

template <typename ReturnType, typename... Args> 
std::function<ReturnType (Args...)> memoize(std::function<ReturnType (Args...)> func) 
{ 
    std::map<std::tuple<Args...>, ReturnType> cache; 
    return ([=](Args... args) mutable { 
      std::tuple<Args...> t(args...); 
auto range = cache.equal_range(t); 
if (range.first != range.second) return (*range.first).second; 
return (*cache.insert(range.first, func(args...))).second; 

    }); 
} 

Compiler ошибка:

In instantiation of 'memoize(std::function<_Res(_ArgTypes ...)>)::<lambda(Args ...)> mutable [with ReturnType = int; Args = {int, int}]': 
14:36: required from 'struct memoize(std::function<_Res(_ArgTypes ...)>) [with ReturnType = int; Args = {int, int}]::<lambda(int, int)>' 
16:6: required from 'std::function<_Res(_ArgTypes ...)> memoize(std::function<_Res(_ArgTypes ...)>) [with ReturnType = int; Args = {int, int}]' 
34:56: required from here 
14:9: error: no matching function for call to 'std::map<std::tuple<int, int>, int, std::less<std::tuple<int, int> >, std::allocator<std::pair<const std::tuple<int, int>, int> > >::insert(std::_Rb_tree_iterator<std::pair<const std::tuple<int, int>, int> >&, int)' 
14:9: note: candidates are: 
In file included from /usr/include/c++/4.9/map:61:0, 
       from 1: 
/usr/include/c++/4.9/bits/stl_map.h:629:7: note: std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const std::tuple<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const std::tuple<int, int>, int>] 
     insert(const value_type& __x) 
    ^
/usr/include/c++/4.9/bits/stl_map.h:629:7: note: candidate expects 1 argument, 2 provided 
/usr/include/c++/4.9/bits/stl_map.h:637:9: note: template<class _Pair, class> std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(_Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >] 
     insert(_Pair&& __x) 
     ^
/usr/include/c++/4.9/bits/stl_map.h:637:9: note: template argument deduction/substitution failed: 
14:9: note: candidate expects 1 argument, 2 provided 
In file included from /usr/include/c++/4.9/map:61:0, 
       from 1: 
/usr/include/c++/4.9/bits/stl_map.h:650:7: note: void std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::initializer_list<std::pair<const _Key, _Tp> >) [with _Key = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >] 
     insert(std::initializer_list<value_type> __list) 
    ^
/usr/include/c++/4.9/bits/stl_map.h:650:7: note: candidate expects 1 argument, 2 provided 
/usr/include/c++/4.9/bits/stl_map.h:679:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::tuple<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const std::tuple<int, int>, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const std::tuple<int, int>, int>] 
     insert(const_iterator __position, const value_type& __x) 
    ^
/usr/include/c++/4.9/bits/stl_map.h:679:7: note: no known conversion for argument 2 from 'int' to 'const value_type& {aka const std::pair<const std::tuple<int, int>, int>&}' 
/usr/include/c++/4.9/bits/stl_map.h:690:9: note: template<class _Pair, class> std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::insert(std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator, _Pair&&) [with _Pair = _Pair; <template-parameter-2-2> = <template-parameter-1-2>; _Key = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >] 
     insert(const_iterator __position, _Pair&& __x) 
     ^
/usr/include/c++/4.9/bits/stl_map.h:690:9: note: template argument deduction/substitution failed: 
/usr/include/c++/4.9/bits/stl_map.h:686:32: error: no type named 'type' in 'struct std::enable_if<false, void>' 
     template<typename _Pair, typename = typename 
           ^
/usr/include/c++/4.9/bits/stl_map.h:705:9: note: template<class _InputIterator> void std::map<_Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = std::tuple<int, int>; _Tp = int; _Compare = std::less<std::tuple<int, int> >; _Alloc = std::allocator<std::pair<const std::tuple<int, int>, int> >] 
     insert(_InputIterator __first, _InputIterator __last) 
     ^
+3

Если у вас есть 2 вопроса, вы должны создать два отдельных вопроса. – wimh

+2

Если вы получаете ошибку компилятора, вы должны скопировать и вставить эту ошибку в свой вопрос. – NathanOliver

+2

Помечается как (щедро ИМО) непонятно, что-вы спрашиваете, так как вы активно отказываетесь сообщать нам, какую ошибку вы получаете, и вы не можете решить между этим неопровержимым вопросом или совершенно другим. Я имею в виду, действительно - «Я не буду сообщать об ошибке, чтобы сообщение было чистым» - вы шутите? –

ответ

2

Ошибка внутри лямбда:

auto range = cache.equal_range(t); 
... 
... cache.insert(range.first, func(args...)) ... 

и

14:9: error: no matching function for call to 
'std::map<std::tuple<int, int>, int,...> 
    ::insert(std::_Rb_tree_iterator<...>&, int)' 

Это говорит вам, что вы вызываете вставить неправильно ,

Диапазон вернулся из equal_range пара итераторов - вам необходимо разыменования итератора первого и взять первый (ключ) элемент, чтобы получить пару ключ/значение, которое вы хотите. То есть, что-то вроде

cache.insert(range.first, make_pair(t, func(args...))) 

В общем, вы можете помочь себе понять эти ошибки путем:

  • упрощающего кода (эти большие составные высказывания означают много вещей происходит, и есть много потенциальных ошибок, в одной строке),
  • от внимательно прочитал сообщение об ошибке (он перечисляет столбец и говорит, что проблема связана с insert,
  • , и если все остальное не удается воспроизвести ошибку в минимальном примере (удаление кода, не связанного с ошибкой, уменьшает количество вопросов, которые необходимо учитывать).

 Смежные вопросы

  • Нет связанных вопросов^_^