нет == определено для boost :: tuples

У меня есть этот код:

...
#include "boost/tuple/tuple_comparison.hpp"...
template <typename ReturnType, typename... Args>
function<ReturnType(Args...)> memoize(const Args && ... args)
{
using noRef = boost::tuple<typename std::remove_reference<Args>::type...>;
static map<noRef, ReturnType, less<>> cache;
auto key = std::tie(noRef{ boost::make_tuple(args ...) });
auto it = cache.lower_bound(key);
ReturnType result;
if (it->first == key) { ...

Но когда я пытаюсь скомпилировать его, я получаю эту ошибку:

error C2678: binary '==': no operator found which takes a left-hand operand of type 'const noRef' (or there is no acceptable conversion)

Почему это происходит, так как noRef это псевдоним для boost::tuple а также tuple_comparison должен управлять этим делом?

ОШИБКА НАЙДЕНА, НЕ ЗНАЮ, КАК ЕГО РЕШИТЬ:

Похоже, ошибка была в std::tie операция. Так что переписать это как:

    auto key = noRef{ boost::make_tuple(args ...) };

Работает отлично. Проблема в том, что это решение неэффективно, так как key является потенциально дорогой копией всего кортежа, при использовании tie это кортеж ссылок (гораздо меньше). Итак, как я могу взять ссылку на it->first кортеж? Должен ли я использовать то же самое tie трюк?

1

Решение

Единственная причина, по которой эта строка компилируется — это расширение MSVC Evil Extension.TM который позволяет неконстантным ссылкам lvalue связываться с временными файлами:

auto key = std::tie(noRef{ boost::make_tuple(args ...) });

Это должно быть просто

auto key = boost::tie(args...);

который создает boost::tuple ссылок, которые будут использоваться для поиска позже.

Также, как отмечено в комментариях, if проверка должна проверить it != cache.end() сначала, прежде чем пытаться разыменовать его (спасибо!).

В заключение, const Args && ... не имеет особого смысла, так как вряд ли кто-то захочет принять постоянные значения. Это, вероятно, должно быть либо const Args&... или же Args&&...,

2

Другие решения

Других решений пока нет …