我根据提案开始实施expected<E, T>
,但遇到了问题。
在描述monadic功能(5.9)时,在bind中声明如果结果已经包含在上下文中(expected<E, T>
),则不应再次包装它。
我如何实现它是绑定有2个重载(带有enable_if
),一个用于返回实例化expected
的仿函数,实现没有将它包装在上下文中,一个用于那些返回了它做的其他类型。我遇到了一个问题,其中非包装版本,在调用者没有值的情况下必须返回默认的构造expected<E1, T1>
,这给出了预期的默认构造错误值。
这导致返回的进一步延续预期会丢失导致默认构造的错误的上下文。
也许我应该对待被称为is_same<expected<E,T>, functor_ret_type>
的上下文,这里如果调用者出错,我可以转发“this”并保留错误的上下文,但这会导致函数返回{ {1}}返回expected<E1, E2>
假设以下有关课程:
expected<E, expected<E1, E2>>
以下是我最初实施的方法:
E& error(); //returns the stored error
T& operator*(); //returns a reference to the stored value
bool has_value(); //returns true if the expected value is present, false if the error is present
在这里你可以看到,在第一个重载中,如果我们没有值,我们返回一个//overload for wrapping functors
template<typename Functor>
auto bind(Functor functor) -> std::enable_if<is_instance<expected,
decltype(functor(**this))>::value,
decltype(functor(**this))>::type
{
using result_type = decltype(functor(**this));
if (this->has_value())
{
return functor(**this);
}
return result_type();
}
//overload for non wrapping functors
template<typename Functor>
auto bind(Functor functor) -> std::enable_if<!is_instance<expected,
decltype(functor(**this))>::value,
expected<E, decltype(functor(**this))>>::type
{
using result_type = decltype(functor(**this));
if (has_value())
{
return { functor(**this) };
}
return expected<E, result_type>(this->error());
}
返回类型的默认构造expected<E, T>
,它包含一个默认的构造错误类型{{1因为没有调用functor,我们会失去原始错误的上下文。
如果我将所描述的行为解释为“如果functor返回与调用绑定类型相同类型的functor
,请不要换行换行”我们可以进行以下实现:
E
这里,如果包装重载中没有值,我们转发expected<E, T>
,这可以让我们知道什么是初始错误,但如果functor返回//overload for wrapping functors
template<typename Functor>
auto bind(Functor functor) -> std::enable_if<is_same<expected<E, T>,
decltype(functor(**this))>::value,
decltype(functor(**this))>::type
{
if (this->has_value())
{
return functor(**this);
}
return *this;
}
//overload for non wrapping functors
template<typename Functor>
auto bind(Functor functor) -> std::enable_if<!is_same<expected<E, T>,
decltype(functor(**this))>::value,
expected<E, decltype(functor(**this))>>::type
{
using result_type = decltype(functor(**this));
if (has_value())
{
return { functor(**this) };
}
return expected<E, result_type>(this->error());
}
,结果将是一个包裹this
1}}
我能想到的第三种方法是仅将expected<E1, T1>
视为上下文,这种限制会稍微限制一些,并且允许解包返回expected<E, expected<E1, T1>>
的仿函数,但问题是{ {1}}仍然存在。
哪种方法正确?也许我完全错过了另一种方法?
谢谢。
答案 0 :(得分:1)
bind
是根据unwrap
:
template <class Ex,class F> ’see below’ expected<E,T>::bind(F&& func)
返回: - 如果
bool(*this)
返回unwrap(expected<E, decltype(func(move(val)))>(func(move(val))))
,否则返回get_unexpected()
。
在https://isocpp.org/files/papers/n4015.pdf和http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4015.pdf unwrap
中,只为expected<E,expected<E,U>>
提供了非平凡的语义;也就是说,两个意外类型E
必须相同:
template <class E, class U> constexpr expected<E,U> expected<E,expected<E,U>>::unwrap() const&;
返回: - 如果
bool(*this)
则**this
。别的get_unexpected()
如果有两种不同的意外类型E1
,E2
则unwrap
无效。