此问题中的代码使用此处的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()
的{{1}}也一样。我知道right()
可能会产生段错误,因为您已经调用了两次,在这种情况下,std::future::get
会在调用std::future::valid
之前返回false,但get
会返回true
这里有什么我想念的吗?
答案 0 :(得分:11)
这里有什么我想念的吗?
图书馆未正确实施。特别是出于这个问题的目的,copy constructor是错误的:
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);