std :: future & lt; none :: Either & lt; int, std :: string & gt; & gt; ошибка сегментации

Код в этом вопросе использует Either<> Реализация найдена здесь: https://github.com/LoopPerfect/neither. Чтобы было ясно, я сомневаюсь, что это проблема с этой конкретной библиотекой, иначе я бы создал проблему там.

Следующий фрагмент работает как положено:

std::future<std::string> f = std::async(std::launch::async, []()
{
return "test";
}

std::cout << f.get() << std::endl;

И следующее генерирует ошибку сегментации:

std::future<neither::Either<int, std::string>> f = std::async(std::launch::async, []()
{
return neither::Either<int, std::string>(neither::right(std::string("test")));
});

neither::Either<int, std::string> v = f.get(); // Segmentation fault
std::cout << v.right().value << std::endl;

возврате left(-1) работает, как и neither::Either<int, int> для обоих left() а также right(), я знаю это std::future::get может генерировать segfault, что вы вызвали его дважды, в этом случае std::future::valid вернет false перед вызовом get, но valid возвращает истину.

Есть что-то, чего я здесь не хватает?

4

Решение

Есть что-то, чего я здесь не хватает?

Библиотека не реализована должным образом. Специально для целей этого вопроса конструктор копирования неправильно:

constexpr Either( Either<L, R> const& e )
: isLeft(e.isLeft) {
if(isLeft) {
leftValue = e.leftValue;
} else {
rightValue = e.rightValue; // (*)
}
}

Мы не можем назначить this->rightValue там нет std::string существует в этом месте — у нас неинициализированная память.

Правильный конструктор копирования будет:

Either(Either<L, R> const& e)
: isLeft(e.isLeft)
{
if(isLeft) {
new (&leftValue) L(e.leftValue);
} else {
new (&rightValue) R(e.rightValue);
}
}

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

::new (static_cast<void*>(std::addressof(leftValue))) L(e.leftValue);
11

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

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

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector