此问题与decltype
和多重继承有关。
假设我有以下内容:
例如:
#include <iostream>
/**
* "Iterable container"
*/
template <class T>
struct A
{
virtual T* data() =0;
virtual const T* data() const =0;
virtual unsigned size() const =0;
T* begin() { return data(); }
T* end() { return data()+size(); }
const T* begin() const { return data(); }
const T* end() const { return data()+size(); }
};
// ------------------------------------------------------------------------
/**
* Iterative assignment
*/
template <class T>
struct B: public A<T>
{
auto operator =( const T& val ) -> decltype(*this)
{
for ( auto& v: *this ) v = val;
return *this;
}
};
/**
* Iterative display
*/
template <class T>
struct C: public A<T>
{
void show() const
{
for ( auto& v: *this )
std::cout<< v << " ";
std::cout<< std::endl;
}
};
// ------------------------------------------------------------------------
/**
* Concrete implementation
*/
template <class T, unsigned N>
struct D:
public B<T>,
public C<T>
{
using B<T>::operator=;
T dat[N];
T* data() { return dat; }
const T* data() const { return dat; }
unsigned size() const { return N; }
};
// ------------------------------------------------------------------------
int main()
{
D<double,5> d;
(d = 42).show(); // compile-time error, "no member named 'show' in 'B<double>'"
}
问题是这个(没有双关语意);如果其中一个&#34;用例&#34;方法应该返回对*this
的引用,我希望this
是对最终具体类的引用,这样我就可以使用其他用例中的其他方法来链接调用。
然而,在之前的实现中,我遇到了编译时错误。还有另一种方法可以实现我的解释吗?
答案 0 :(得分:4)
解决方案是使用CRTP;通过将最派生类型作为附加模板参数传递,告诉B
返回对D<T, N>
的左值引用。
template <class T, class Derived>
struct B: public A<T>
{
auto operator =( const T& val ) -> Derived&
// ...
template <class T, unsigned N>
struct D:
public B<T, D<T, N>>,
// ...
答案 1 :(得分:3)
您可以为D
提供一个返回operator=
的覆盖D &
:
auto operator =( const T& val ) -> decltype(*this) override
{
B<T>::operator=(val);
return *this;
}
这是有效的,因为D &
与B &
是协变的,并且重写函数必须具有协变返回类型。目前这也会影响B
operator=
,因为那个不是virtual
。