Fix circular dependency in arithmetic class

柔情痞子 提交于 2019-12-12 03:33:36

问题


I have a set of classes implementing the curiously recurring template pattern. However, the trick is that the base class needs to return instances of the subclasses. Here's an example:

template <typename SubType>
class ArithmeticBase
{
public:
    template <typename OtherType>
    const Addition operator+(const OtherType &other)
        {return Addition(get_subclass(), other);}

    // ...
    // Operators for subtraction, multiplication, division, ...

private:
    const SubType &get_subclass() const
        {return *static_cast<const SubType*>(this);}
};

template <typename OperatorType1, typename OperatorType2>
class Addition : ArithmeticBase<Addition<OperatorType1, OperatorType2>>
{
public:
    Addition(const OperatorType1 &op1, const OperatorType2 &op2)
        : op1(op1)
        , op2(op2)
    {}

private:
    const OperatorType1 &op1;
    const OperatorType2 &op2;
};

// ...
// Additional classes for subtraction, multiplication, division, ...

Compiling this fails because the Addition class is not defined before it's used in the ArithmeticBase class:

arithmetic.cpp:6:8: error: unknown type name 'Addition'
        const Addition operator+(const OtherType &other)
              ^

How can I resolve this?


回答1:


You could forward declare Addition before the base class.

template <typename OperatorType1, typename OperatorType2>
class Addition;
template <typename SubType>
class ArithmeticBase
{
...
};

This allows the compiler to know there is a type Addition that exists before it is defined.




回答2:


Or use non-member form declared after Addition:

template <typename OperatorType1, typename OperatorType2>
class Addition;

template <typename SubType>
class ArithmeticBase
{
public:

     template <typename OneType, typename OtherType>
     friend const Addition<OneType, OtherType> operator+(const ArithmeticBase<OneType>& one, const OtherType &other);

private:
    const SubType &get_subclass() const
    {
        return *static_cast<const SubType*>(this);
    }
};

class ArithmeticType : public ArithmeticBase < ArithmeticType > {};

template <typename OperatorType1, typename OperatorType2>
class Addition : ArithmeticBase<Addition<OperatorType1, OperatorType2>>
{
public:
    Addition(const OperatorType1 &op1, const OperatorType2 &op2)
        : op1(op1)
        , op2(op2)
    {}

private:
    const OperatorType1 &op1;
    const OperatorType2 &op2;
};


template <typename OneType, typename OtherType>
const Addition<OneType, OtherType> operator+(const ArithmeticBase<OneType>& one, const OtherType &other)
{
    return Addition<OneType, OtherType>(one.get_subclass(), other);
}

int main()
{
    ArithmeticType a, b;
    a + b;
}



回答3:


In addition to forward declaring the Addition class (as bhzag's answer shows) you'll need to move the definition of operator+ to after the definition the Addition class. Otherwise you'll get an error on the next line.

Make sure the definition is in the header file. If it isn't, you'll get linker errors.



来源:https://stackoverflow.com/questions/31614278/fix-circular-dependency-in-arithmetic-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!