【问题标题】:Memoization code in C++: why it doesn't work?C++ 中的记忆代码:为什么它不起作用?
【发布时间】:2016-04-13 11:45:46
【问题描述】:

我收到了this example 关于在 C++ 中实现通用记忆的信息。但是,正如有人在this 评论中指出的那样,原始代码进行了 2 次查找,而下面的代码仅进行了一次。

唯一的问题是第二个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;

    });
}

编译器错误:

 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)
         ^

【问题讨论】:

  • 如果您有 2 个问题,您应该创建两个单独的问题。
  • 如果您遇到编译器错误,您应该将该错误复制并粘贴到您的问题中。
  • 标记为(慷慨地 IMO)不清楚你在问什么,因为你主动拒绝告诉我们你遇到了什么错误,而且你似乎无法决定是那个无法回答的问题还是一个完全不同的一个。我的意思是,真的 - “我不会报告错误以保持帖子干净” - 你在开玩笑吗?
  • 对不起大家,我已经报告了编译器错误。
  • 为第二个问题创建了新问题:stackoverflow.com/questions/36597697/…

标签: c++ memoization


【解决方案1】:

错误在您的 lambda 中:

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)'

它告诉你你调用 insert 错误。

equal_range 返回的范围是一对迭代器——您需要取消对第一个迭代器的引用获取第一个(键)元素,以获得您想要的键/值对。也就是说,像

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

一般来说,您可以通过以下方式帮助自己找出这些错误:

  • 简化您的代码(这些大的复合语句意味着很多事情正在发生,并且有很多潜在的错误,在一行中),
  • 通过仔细阅读错误消息(它确实列出了该列,并说问题出在insert
  • 如果所有其他方法都失败,则通过在一个最小示例中重现错误(删除与错误无关的代码可减少要考虑的问题数量)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 2017-11-07
    • 2017-06-15
    • 1970-01-01
    • 2021-11-03
    • 2018-09-01
    • 1970-01-01
    相关资源
    最近更新 更多