使用奇怪的循环模板模式 (CRTP) 在抽象基础 class 中实现赋值运算符
Implementing the assignment operator in an abstract base class using the curiously recurring template pattern (CRTP)
我正在为 static/dynamic 数组编写基于 CRTP 的抽象基础 class。我打算在基础 class 中放置尽可能多的方法,以便在派生的 class 中没有代码重复。我已经让索引运算符工作,但我正在努力处理赋值 (=) 运算符。
/** Array base class. */
template <class t_derived_class, class data_type>
class ArrayBase
{
private:
t_derived_class& Derived;
public:
/** Default constructor. */
ArrayBase() : Derived(static_cast<t_derived_class&>(*this)) {}
/** Pure virtual desctructor. */
virtual ~ArrayBase() {};
/** Index operator overloads. */
data_type& operator[](const std::size_t _index)
{
return *(Derived.begin() + _index);
}
const data_type& operator[](const std::size_t _index) const
{
return *(Derived.begin() + _index);
}
/** Assignment operator overloads. */
t_derived_class& operator=(const t_derived_class& _other_derived)
{
for(std::size_t i = 0; i < Derived.size(); ++i) Derived[i] = _other_derived[i];
return Derived;
}
};
/** Static array class. */
template <class data_type, int array_size>
class StaticArray : public std::array<data_type, array_size>, public ArrayBase<StaticArray<data_type, array_size>, data_type>
{
using Base = ArrayBase<StaticArray<data_type, array_size>, data_type>;
friend Base;
public:
/** Default constructor. */
StaticArray() : std::array<data_type, array_size>() {}
/** Default destructor. */
~StaticArray() = default;
using Base::operator[];
using Base::operator=;
};
/** Dynamic array class. */
template <class data_type>
class DynamicArray : public std::vector<data_type>, public ArrayBase<DynamicArray<data_type>, data_type>
{
// ...
};
int main()
{
StaticArray<double, 3> array1;
array1[0] = 1.0;
array1[1] = 2.0;
array1[2] = 3.0;
// This code compiles
StaticArray<double, 3> array2 = array1;
// This code does not compile
array2 = array1;
return 0;
}
我的 IDE (CLion) 在我使用上述赋值运算符时出现以下错误:
Object of type 'StaticArray<Apeiron::Float, 3>' (aka 'StaticArray<double, 3>') cannot be assigned because its copy assignment operator is implicitly deleted
编译器错误是:
error: ‘Apeiron::StaticArray<double, 3>& Apeiron::StaticArray<double, 3>::operator=(const Apeiron::StaticArray<double, 3>&)’ cannot be overloaded with ‘t_derived_class& Apeiron::ArrayBase<t_derived_class, data_type>::operator=(const t_derived_class&) [with t_derived_class = Apeiron::StaticArray<double, 3>; data_type = double]’
90 | class StaticArray : public std::array<data_type, array_size>, public ArrayBase<StaticArray<data_type, array_size>, data_type>
| ^~~~~~~~~~~
Array.h:62:20: note: previous declaration ‘t_derived_class& Apeiron::ArrayBase<t_derived_class, data_type>::operator=(const t_derived_class&) [with t_derived_class = Apeiron::StaticArray<double, 3>; data_type = double]’
62 | t_derived_class& operator=(const t_derived_class& _other_derived)
任何人都可以告诉我如何让它工作吗?
由于您的 ArrayBase
的成员变量是 reference,隐式声明的 ArrayBase::operator=
将是 automatically deleted.
另一种方法是去掉成员变量,直接使用帮助函数得到派生的reference:class:
template <class t_derived_class, class data_type>
class ArrayBase
{
private:
t_derived_class& Derived() noexcept {
return static_cast<t_derived_class&>(*this);
};
const t_derived_class& Derived() const noexcept {
return static_cast<const t_derived_class&>(*this);
};
public:
/** Pure virtual desctructor. */
virtual ~ArrayBase() {};
/** Index operator overloads. */
data_type& operator[](const std::size_t _index)
{
return *(Derived().begin() + _index);
}
// ...
};
我正在为 static/dynamic 数组编写基于 CRTP 的抽象基础 class。我打算在基础 class 中放置尽可能多的方法,以便在派生的 class 中没有代码重复。我已经让索引运算符工作,但我正在努力处理赋值 (=) 运算符。
/** Array base class. */
template <class t_derived_class, class data_type>
class ArrayBase
{
private:
t_derived_class& Derived;
public:
/** Default constructor. */
ArrayBase() : Derived(static_cast<t_derived_class&>(*this)) {}
/** Pure virtual desctructor. */
virtual ~ArrayBase() {};
/** Index operator overloads. */
data_type& operator[](const std::size_t _index)
{
return *(Derived.begin() + _index);
}
const data_type& operator[](const std::size_t _index) const
{
return *(Derived.begin() + _index);
}
/** Assignment operator overloads. */
t_derived_class& operator=(const t_derived_class& _other_derived)
{
for(std::size_t i = 0; i < Derived.size(); ++i) Derived[i] = _other_derived[i];
return Derived;
}
};
/** Static array class. */
template <class data_type, int array_size>
class StaticArray : public std::array<data_type, array_size>, public ArrayBase<StaticArray<data_type, array_size>, data_type>
{
using Base = ArrayBase<StaticArray<data_type, array_size>, data_type>;
friend Base;
public:
/** Default constructor. */
StaticArray() : std::array<data_type, array_size>() {}
/** Default destructor. */
~StaticArray() = default;
using Base::operator[];
using Base::operator=;
};
/** Dynamic array class. */
template <class data_type>
class DynamicArray : public std::vector<data_type>, public ArrayBase<DynamicArray<data_type>, data_type>
{
// ...
};
int main()
{
StaticArray<double, 3> array1;
array1[0] = 1.0;
array1[1] = 2.0;
array1[2] = 3.0;
// This code compiles
StaticArray<double, 3> array2 = array1;
// This code does not compile
array2 = array1;
return 0;
}
我的 IDE (CLion) 在我使用上述赋值运算符时出现以下错误:
Object of type 'StaticArray<Apeiron::Float, 3>' (aka 'StaticArray<double, 3>') cannot be assigned because its copy assignment operator is implicitly deleted
编译器错误是:
error: ‘Apeiron::StaticArray<double, 3>& Apeiron::StaticArray<double, 3>::operator=(const Apeiron::StaticArray<double, 3>&)’ cannot be overloaded with ‘t_derived_class& Apeiron::ArrayBase<t_derived_class, data_type>::operator=(const t_derived_class&) [with t_derived_class = Apeiron::StaticArray<double, 3>; data_type = double]’
90 | class StaticArray : public std::array<data_type, array_size>, public ArrayBase<StaticArray<data_type, array_size>, data_type>
| ^~~~~~~~~~~
Array.h:62:20: note: previous declaration ‘t_derived_class& Apeiron::ArrayBase<t_derived_class, data_type>::operator=(const t_derived_class&) [with t_derived_class = Apeiron::StaticArray<double, 3>; data_type = double]’
62 | t_derived_class& operator=(const t_derived_class& _other_derived)
任何人都可以告诉我如何让它工作吗?
由于您的 ArrayBase
的成员变量是 reference,隐式声明的 ArrayBase::operator=
将是 automatically deleted.
另一种方法是去掉成员变量,直接使用帮助函数得到派生的reference:class:
template <class t_derived_class, class data_type>
class ArrayBase
{
private:
t_derived_class& Derived() noexcept {
return static_cast<t_derived_class&>(*this);
};
const t_derived_class& Derived() const noexcept {
return static_cast<const t_derived_class&>(*this);
};
public:
/** Pure virtual desctructor. */
virtual ~ArrayBase() {};
/** Index operator overloads. */
data_type& operator[](const std::size_t _index)
{
return *(Derived().begin() + _index);
}
// ...
};