c++ - C++ 中的求和类型

标签 c++ templates virtual-functions variant strong-typedef

在工作中,我遇到了一种情况,描述函数返回结果的最佳类型是 std::variant<uint64_t, uint64_t> - 当然,这不是有效的 C++,因为你不能有两个相同类型的变体。我可以将其表示为 std::pair<bool, uint64_t> , 或者该对的第一个元素是枚举,但这是一种特殊情况; std::variant<uint64_t, uint64_t, bool>不太清楚,而且我的函数式编程背景真的让我想要 Either - 所以我去尝试实现它,使用访问者模式,因为我已经能够在没有对 sum 类型的本地支持的情况下在其他语言中做到这一点:

template <typename A, typename B, typename C>
class EitherVisitor {
    virtual C onLeft(const A& left) = 0;
    virtual C onRight(const B& right) = 0;
};

template <typename A, typename B>
class Either {
    template <typename C>
    virtual C Accept(EitherVisitor<A, B, C> visitor) = 0;
};

template <typename A, typename B>
class Left: Either<A, B> {
private:
    A value;
public:
    Left(const A& valueIn): value(valueIn) {}

    template <typename C>
    virtual C Accept(EitherVisitor<A, B, C> visitor) {
        return visitor.onLeft(value);
    }
};

template <typename A, typename B>
class Right: Either<A, B> {
private:
    B value;
public:
    Right(const B& valueIn): value(valueIn) {}
    
    template <typename C>
    virtual C Accept(EitherVisitor<A, B, C> visitor) {
        return visitor.onRight(value);
    }
};
C++ 拒绝这个,因为模板方法 Accept不能是虚拟的。是否有解决此限制的方法,这将允许我根据其 f 代数和变形来正确表示基本和类型?

最佳答案

也许最简单的解决方案是围绕 T 使用轻量级包装器。为 RightLeft ?
基本上是一个强类型别名(也可以使用 Boost 的 strong typedef )

template<class T>
struct Left
{
    T val;
};

template<class T>
struct Right
{
    T val;
};
然后我们可以区分它们进行访问:
template<class T, class U>
using Either = std::variant<Left<T>, Right<U>>;

Either<int, int> TrySomething()
{
    if (rand() % 2 == 0) // get off my case about rand(), I know it's bad
        return Left<int>{0};
    else
        return Right<int>{0};
}

struct visitor
{
    template<class T>
    void operator()(const Left<T>& val_wrapper)
    {
        std::cout << "Success! Value is: " << val_wrapper.val << std::endl;
    }
    
    template<class T>
    void operator()(const Right<T>& val_wrapper)
    {
        std::cout << "Failure! Value is: " << val_wrapper.val << std::endl;
    }
};

int main()
{
    visitor v;
    for (size_t i = 0; i < 10; ++i)
    {
        auto res = TrySomething();
        std::visit(v, res);
    }
}
Demo

关于c++ - C++ 中的求和类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64779163/

相关文章:

c++ - 在 C++ 类中使用虚拟方法的性能成本是多少?

c++ - 这是gcc的错误吗?

c++ - 在每个 Qt Creator 项目中添加 C++11 支持

c++ - 应用程序无法正确启动(0x000007b)

c++ - 模板参数是否可以进行矩阵乘法

c++ - 按值接受临时值和按引用接受非临时值的模板函数?

c++ - 仅在具有零参数模板的头文件中定义 C++ 全局函数?

c++ - Direct3D11 是否包含色彩空间转换?

c# - 如何从 C++ DLL 动态加载 C# dll

c++ - 如何设计一个 "Awaitable"基类?