【问题标题】:C++ template meta programming: overloading operatorsC++ 模板元编程:重载运算符
【发布时间】:2017-01-13 01:57:32
【问题描述】:

我目前正在玩模板元编程。我正在尝试使用 tmp 制作一个有限状态机。我知道网络上有几种实现,但我想自己实现一个作为练习。

我正在尝试为基类中的模板化基类的模板化衍生物重载运算符。假设我们有一个基类:

template<typename Input>
class Base
{
public:
    virtual ~Base() = default;    
    virtual bool operator()(const Input& input) const = 0;

    template<typename Lhs, typename Rhs>
    constexpr Derivation1<Input, Lhs, Rhs> operator||(const Lhs& left, const Rhs& right) const;

    template<typename Lhs, typename Rhs>
    constexpr Derivation2<Input, Lhs, Rhs> operator&&(const Lhs& left, const Rhs& right) const;
};

及其2个派生词:

template<typename Input, typename... TSpecialized>
class Derivation1 : public Base<Input>
{
public:
    bool operator()(const Input& input) const override
    {
        // ...
    }
};

template<typename Input, typename... TSpecialized>
class Derivation2 : public Base<Input>
{
public:
    bool operator()(const Input& input) const override
    {
        // ...
    }
};

以及我们在基类中声明的运算符的定义:

template <typename Input>
template <typename Lhs, typename Rhs>
constexpr Derivation1<Input, Lhs, Rhs> Base<Input>::operator||(const Lhs& left, const Rhs& right) const
{
    return Derivation1<Input, Lhs, Rhs>();
}

template <typename Input>
template <typename Lhs, typename Rhs>
constexpr Derivation2<Input, Lhs, Rhs> Base<Input>::operator&&(const Lhs& left, const Rhs& right) const
{
    return Derivation2<Input, Lhs, Rhs>();
}

Rhs 和 Lhs 类型也是基类的派生。

当我尝试使用以下运算符时:

Derivation3<int, 10, 20> left;
Derivation4<int, 300, 290> right;

auto result = left || right;

我收到一条错误消息,指出运算符的重载与参数不匹配。两个派生具有相同的基类型:Base&lt;int&gt;,其中应声明重载。变量result 应该是Derivation1 类型(就像我们在上面的代码中声明的那样)。

在这种情况下如何正确地重载操作员?

【问题讨论】:

    标签: c++ operator-overloading template-meta-programming


    【解决方案1】:

    我找到了解决方案。我在基类中创建了一个 typedef:

    template<typename Input>
    class Base
    {
    public:
        virtual ~Base() = default;    
        virtual bool operator()(const Input& input) const = 0;
    
        typedef Input inputType;
    };
    

    我将运算符重载移到了类之外:

    template <typename Lhs, typename Rhs>
    constexpr Derivation1<typename Lhs::inputType, Lhs, Rhs> operator||(const Lhs& left, const Rhs& right)
    {
        return Derivation1<typename Lhs::inputType, Lhs, Rhs>();
    }
    
    template <typename Lhs, typename Rhs>
    constexpr Derivation2<typename Lhs::inputType, Lhs, Rhs> operator&&(const Lhs& left, const Rhs& right)
    {
        return Derivation2<typename Lhs::inputType, Lhs, Rhs>();
    }
    

    此代码按预期完美运行。

    【讨论】:

    • 如果编译器允许函数在Base 中声明,那真是令人惊讶;他们需要friend 说明符。
    猜你喜欢
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多