是否存在"动态decltype"?

时间:2014-08-26 13:51:15

标签: c++ c++11 multiple-inheritance decltype

此问题与decltype和多重继承有关。

假设我有以下内容:

  • 带有一些虚拟方法的抽象类A,
  • 使用以前的虚拟方法实现方法的一些派生类(这些类中的每一个都是一种用例),
  • 最后一个具体类,它继承了以前用例的一个子集,并实现了纯虚方法。

例如:

#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是对最终具体类的引用,这样我就可以使用其他用例中的其他方法来链接调用。

然而,在之前的实现中,我遇到了编译时错误。还有另一种方法可以实现我的解释吗?

2 个答案:

答案 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