std :: async затухающая (теряющая) ссылка на rvalue в Visual Studio 2012, обновление 2. Есть ли обходные пути?

Рассмотрим следующий код:

#include <memory>
#include <future>

using namespace std;

template <typename T, typename Work>
void Test2(future<T> f, Work w)
{
async([](future<T> && f, Work w)
{}, move(f), move(w));
}

int main()
{
future<int> x = std::async([]()->int{
std::this_thread::sleep_for(std::chrono::microseconds(200));
return 10;
});

Test2(std::move(x), [](int x){});
return 0;
}

Выше, терпит неудачу со следующей ошибкой компилятора:

Ошибка 1 ошибка C2664: ‘void
Test2 :::: оператор
() (Станд :: будущее<_Ty> &&, Работа) const ‘: невозможно преобразовать параметр 1 из
«Станд :: будущее<_Ty> ‘to’ std :: future<_Ty> &&’c: \ программные файлы
(x86) \ Microsoft Visual Studio
11.0 \ vc \ include \ xrefwrap 98 1 ConsoleApplication6

GCC 4.7.2 компилируется просто отлично
http://ideone.com/KhMiV6

Прежде чем я начну и сообщу об этом в Microsoft Connect:

1) Это ошибка со стороны VC11 или это действительно стандартное поведение?

2) Кто-нибудь знает об обходном пути для этого?

РЕДАКТИРОВАТЬ: я сообщил об этом Microsoft Connect здесь. Для более быстрого разрешения вам рекомендуется сделать это.

8

Решение

Хм, похоже, это ошибка в VC11. Видимо реализация async на самом деле не передает аргументы, а копирует их.

В верхней части моей головы я бы создал небольшую оболочку для значения, которое перемещает-создает элемент при копировании оболочки:

    template <typename T>
struct rvref_wrapper {
rvref_wrapper(T&& value) : value_(std::move(value)) {}
rvref_wrapper(rvref_wrapper const& other) : value_ (other.get()) {}
T&& get() const { return std::move(value_); }
mutable T value_;
};

template <typename T>
auto rvref(T&& x) -> rvref_wrapper<typename decay<T>::type> {
return std::move(x);
}

Тогда вам придется изменить ваш тестовый сценарий, чтобы лямбда в Test2 берет обертку вместо future сам:

    template <typename T, typename Work>
void Test2(future<T> f, Work w)
{
async([](rvref_wrapper<future<T>> fr, Work w) {
// acquire future<T>&& here
future<T> f(fr.get());
// e.g. call work with future value
w(f.get());
}, rvref(f), move(w));
}

int main()
{
future<int> x = std::async([]()->int{
std::this_thread::sleep_for(std::chrono::microseconds(200));
return 10;
});

Test2(std::move(x), [](int x){});
return 0;
}

Выглядит немного некрасиво, но, по крайней мере, компилируется. Надеюсь, что это поможет вам!

5

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

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

По вопросам рекламы [email protected]