gpt4 book ai didi

c++ - 在模板类上重载运算符

转载 作者:太空狗 更新时间:2023-10-29 20:08:11 28 4
gpt4 key购买 nike

这是一个 Result 类的定义,旨在模拟 Haskell 中 Either monad 的逻辑(LeftFailure正确成功)。

#include <string>
#include <functional>
#include <iostream>

template <typename S, typename F>
class result
{
private:
S succ;
F fail;
bool pick;

public:
/// Chain results of two computations.
template <typename T>
result<T,F> operator&&(result<T,F> _res) {
if (pick == true) {
return _res;
} else {
return failure(fail);
}
}

/// Chain two computations.
template <typename T>
result<T,F> operator>>=(std::function<result<T,F>(S)> func) {
if (pick == true) {
return func(succ);
} else {
return failure(fail);
}
}

/// Create a result that represents success.
static result success(S _succ) {
result res;
res.succ = _succ;
res.pick = true;

return res;
}

/// Create a result that represents failure.
static result failure(F _fail) {
result res;
res.fail = _fail;
res.pick = false;

return res;
}
};

当尝试使用 && 运算符组合两个结果时,一切正常:

int
main(int argc, char* argv[])
{
// Works!
auto res1 = result<int, std::string>::success(2);
auto res2 = result<int, std::string>::success(3);
auto res3 = res1 && res2;
}

但是当尝试在结果之上进行链式计算时,会出现编译错误:

result<int, std::string>
triple(int val)
{
if (val < 100) {
return result<int, std::string>::success(val * 3);
} else {
return result<int, std::string>::failure("can't go over 100!");
}
}

int
main(int argc, char* argv[])
{
// Does not compile!
auto res4 = result<int, std::string>::success(2);
auto res5a = res4 >>= triple;
auto res5b = res4 >>= triple >>= triple;
}

clang++报错如下:

minimal.cpp:82:21: error: no viable overloaded '>>='
auto res5a = res4 >>= triple;
~~~~ ^ ~~~~~~
minimal.cpp:26:17: note: candidate template ignored: could not match
'function<result<type-parameter-0-0, std::__1::basic_string<char,
std::__1::char_traits<char>, std::__1::allocator<char> > > (int)>' against
'result<int, std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> > > (*)(int)'
result<T,F> operator>>=(std::function<result<T,F>(S)> func) {
^
minimal.cpp:83:32: error: invalid operands to binary expression ('result<int,
std::string> (int)' and 'result<int, std::string> (*)(int)')
auto res5b = res4 >>= triple >>= triple;

关于如何解决这个问题有什么想法吗?

最佳答案

这行得通

auto f = std::function< result<int, std::string>(int)>(triple);
auto res5a = res4 >>= f;

我无法给出简洁明了的解释,仅此而已:类型推导不考虑转换和 tripleresult<int,std::string>()(int)不是std::function .

您不必使用 std::function但您可以接受任何可调用的东西,例如:

template <typename G>
auto operator>>=(G func) -> decltype(func(std::declval<S>())) {
if (pick == true) {
return func(succ);
} else {
return failure(fail);
}
}

Live Demo

请注意 std::function带有一些开销。它使用类型删除来存储各种可调用对象。如果您只想传递一个可调用对象,则无需支付该费用。

对于第二行,@Yksisarvinen 的评论已经对其进行了总结。为了完整起见,我在这里简单地引用它

auto res5b = res4 >>= triple >>= triple; will not work without additional operator for two function pointers or an explicit brackets around res4 >>= triple, because operator >>= is a right-to-left one. It will try first to apply >>= on triple and triple.

PS:我不知道 Either 并且你的代码比我习惯的更实用一些,也许你可以从 std::conditional 中得到类似的东西?

关于c++ - 在模板类上重载运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56467480/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com