自己设计 Result/Either:Success 类型和 Error 类型应该始终不同吗?
Designing own Result/Either: Should Success type and Error type always be destinct?
我有一个用于 C++ 的 Result
/Either
的实现。 class 功能遵循 type-converting constructor:
template <typename V, typename E>
class Result {
...
template<typename X>
constexpr Result(X&& value);
...
};
这样做的目的是启用这样的代码:
Result<SomeType, int> value = SomeType{...};
EXPECT_TRUE(result.isOk()); // TRUE
// Also
Result<SomeType, int> value = 10;
EXPECT_TRUE(result.isError()); // TRUE
这对于函数 returning 值很重要:
Result<SuccessType, int> func() {
SuccessType result{...};
...
return result;
}
...
EXPECT_TRUE(func().isOk());
现在事实证明,这样的构造函数过于宽松,会导致不受欢迎的类型conversion.s我想对其进行约束。
所以问题是:
- 你认为允许相同类型的值结果和错误有用吗?例如:
Result<MyTypeA, MyTypeA> r{};
有没有错误类型和成功类型相同的例子有用?
这个问题的动机是我可以摆脱 template<> constructor 但前提是 V 和 E 不是同一类型:
template<class V, class E>
struct Result {
constexpr result(V&& value);
constexpr result(E&& value);
...
- 此外,您认为只有 r 值的构造函数在实践中就足够了吗?
我想不出 Result<> 不是 return 值 - 因此没有必要将值移出中间对象。
如果您是 对称 要么您想要从任何一种类型隐式转换。如果你通过了可以转换为两者的东西,你想失败。
如果您也是 非对称 类型,就像结果一样,您想隐式地从 favored 类型转换。对于不受欢迎的类型,您只想显式转换。
template<class X>
struct Error {
X x;
};
template<class V, class E>
struct Result {
Result( V&& v );
Result( Error<E> e );
// or even:
template<class O,
std::enable_if_t< std::is_convertible_v<O, E>, bool > = true
>
Result( Error<O> e );
};
使用看起来像:
Result<SomeType, int> value = SomeType{...};
EXPECT_TRUE(result.isOk()); // TRUE
// Also
Result<SomeType, int> value = Error{10};
EXPECT_TRUE(result.isError()); // TRUE
并且:
Result<SuccessType, int> func() {
SuccessType result{...};
...
return result;
}
有效,如下:
Result<SuccessType, int> func() {
return Error{10};
}
应避免隐式转换为错误状态,意外访问太容易了。
我有一个用于 C++ 的 Result
/Either
的实现。 class 功能遵循 type-converting constructor:
template <typename V, typename E>
class Result {
...
template<typename X>
constexpr Result(X&& value);
...
};
这样做的目的是启用这样的代码:
Result<SomeType, int> value = SomeType{...};
EXPECT_TRUE(result.isOk()); // TRUE
// Also
Result<SomeType, int> value = 10;
EXPECT_TRUE(result.isError()); // TRUE
这对于函数 returning 值很重要:
Result<SuccessType, int> func() {
SuccessType result{...};
...
return result;
}
...
EXPECT_TRUE(func().isOk());
现在事实证明,这样的构造函数过于宽松,会导致不受欢迎的类型conversion.s我想对其进行约束。
所以问题是:
- 你认为允许相同类型的值结果和错误有用吗?例如:
Result<MyTypeA, MyTypeA> r{};
有没有错误类型和成功类型相同的例子有用?
这个问题的动机是我可以摆脱 template<> constructor 但前提是 V 和 E 不是同一类型:
template<class V, class E>
struct Result {
constexpr result(V&& value);
constexpr result(E&& value);
...
- 此外,您认为只有 r 值的构造函数在实践中就足够了吗? 我想不出 Result<> 不是 return 值 - 因此没有必要将值移出中间对象。
如果您是 对称 要么您想要从任何一种类型隐式转换。如果你通过了可以转换为两者的东西,你想失败。
如果您也是 非对称 类型,就像结果一样,您想隐式地从 favored 类型转换。对于不受欢迎的类型,您只想显式转换。
template<class X>
struct Error {
X x;
};
template<class V, class E>
struct Result {
Result( V&& v );
Result( Error<E> e );
// or even:
template<class O,
std::enable_if_t< std::is_convertible_v<O, E>, bool > = true
>
Result( Error<O> e );
};
使用看起来像:
Result<SomeType, int> value = SomeType{...};
EXPECT_TRUE(result.isOk()); // TRUE
// Also
Result<SomeType, int> value = Error{10};
EXPECT_TRUE(result.isError()); // TRUE
并且:
Result<SuccessType, int> func() {
SuccessType result{...};
...
return result;
}
有效,如下:
Result<SuccessType, int> func() {
return Error{10};
}
应避免隐式转换为错误状态,意外访问太容易了。