修复算术中的循环依赖 class
Fix circular dependency in arithmetic class
我有一组 classes 实现奇怪的重复模板模式。然而,诀窍在于基础 class 需要 return 个子 class 实例。这是一个例子:
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, ...
编译失败,因为 Addition
class 在 ArithmeticBase
class:
中使用之前未定义
arithmetic.cpp:6:8: error: unknown type name 'Addition'
const Addition operator+(const OtherType &other)
^
我该如何解决这个问题?
您可以在基础 class 之前转发声明 Addition
。
template <typename OperatorType1, typename OperatorType2>
class Addition;
template <typename SubType>
class ArithmeticBase
{
...
};
这允许编译器知道有一个类型 Addition
在它被定义之前就已经存在。
除了转发声明 Addition
class(如 bhzag 的回答所示),您还需要将 operator+
的定义移动到定义之后 [=16] =].否则你会在下一行得到一个错误。
确保定义在头文件中。如果不是,您将收到链接器错误。
或使用在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;
}
我有一组 classes 实现奇怪的重复模板模式。然而,诀窍在于基础 class 需要 return 个子 class 实例。这是一个例子:
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, ...
编译失败,因为 Addition
class 在 ArithmeticBase
class:
arithmetic.cpp:6:8: error: unknown type name 'Addition'
const Addition operator+(const OtherType &other)
^
我该如何解决这个问题?
您可以在基础 class 之前转发声明 Addition
。
template <typename OperatorType1, typename OperatorType2>
class Addition;
template <typename SubType>
class ArithmeticBase
{
...
};
这允许编译器知道有一个类型 Addition
在它被定义之前就已经存在。
除了转发声明 Addition
class(如 bhzag 的回答所示),您还需要将 operator+
的定义移动到定义之后 [=16] =].否则你会在下一行得到一个错误。
确保定义在头文件中。如果不是,您将收到链接器错误。
或使用在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;
}