1

我目前正在编写库来处理我的研究领域的小数学向量和矩阵以及一些特殊功能。我目前正在测试一些 CRTP 技巧。以下代码在最后一行产生错误,我不知道为什么:

#include <iostream>
#include <initializer_list>
#include <type_traits>

// Abstract class
template<class TCRTP, class T, unsigned int TSIZE> class AbstractArray
{
    // Constructor
    public:
        inline AbstractArray() : _data{}
        {
            std::cout<<"AbstractArray::AbstractArray()"<<std::endl;
        }

    // Copy constructor
    public:
        template<class TCRTP0, class T0> inline AbstractArray(const AbstractArray<TCRTP0, T0, TSIZE> &rhs)
        {
            std::cout<<"AbstractArray::AbstractArray(const AbstractArray<TCRTP0, T0, TSIZE> &rhs)"<<std::endl;
            for(unsigned int i = 0; i < TSIZE; ++i) {
                _data[i] = rhs[i];
            }
        }

    // Initializer list constructor
    public:
        template<class T0> inline AbstractArray(const std::initializer_list<T0>& rhs)
        {
            std::cout<<"AbstractArray::AbstractArray(const std::initializer_list<T0>& rhs)"<<std::endl;
            const T0* it = rhs.begin();
            for (unsigned int i = 0; i < TSIZE; ++i) {
                _data[i] = *it;
                ++it;
            }
        }

    // Destructor
    public:
        inline ~AbstractArray()
        {
            std::cout<<"AbstractArray::~AbstractArray()"<<std::endl;
        }

    // Subscript operator
    public:
        inline const T& operator[](const unsigned int i) const
        {
            std::cout<<"AbstractArray::operator[](const unsigned int i) const"<<std::endl;
            return _data[i];
        }
        inline T& operator[](const unsigned int i)
        {
            std::cout<<"AbstractArray::operator[](const unsigned int i)"<<std::endl;
            return _data[i];
        }

    // Assignment operator
    public:
        template<class TCRTP0, class T0> inline AbstractArray<TCRTP, T, TSIZE>& operator=(const AbstractArray<TCRTP0, T0, TSIZE>& rhs)
        {
            std::cout<<"AbstractArray::operator=(const AbstractArray<TCRTP0, T0, TSIZE>& rhs)"<<std::endl;
            for (unsigned int i = 0; i < TSIZE; ++i) {
                _data[i] = rhs[i];
            }
            return *this;
        }

    // Sum assignment
    public:
        template<class TCRTP0, class T0> inline AbstractArray<TCRTP, T, TSIZE>& operator+=(const AbstractArray<TCRTP0, T0, TSIZE>& rhs)
        {
            std::cout<<"AbstractArray::operator+=(const AbstractArray<TCRTP0, T0, TSIZE>& rhs)"<<std::endl;
            for (unsigned int i = 0; i < TSIZE; ++i) {
                _data[i] += rhs[i];
            }
            return *this;
        }

    // Sum operator
    public:
        template<class T0> inline AbstractArray<TCRTP, typename std::common_type<T, T0>::type, TSIZE> operator+(const AbstractArray<TCRTP, T0, TSIZE>& rhs) const
        {
            return AbstractArray<TCRTP, typename std::common_type<T, T0>::type, TSIZE>(*this) += rhs;
        }

    // Data members
    protected:
        T _data[TSIZE];
};

// Array class
template<class T, unsigned int TSIZE> class NArray : public  AbstractArray<NArray<T, TSIZE>, T, TSIZE>
{
    // Constructor
    public:
        inline NArray() : AbstractArray<NArray<T, TSIZE>, T, TSIZE>()
        {
            std::cout<<"NArray::NArray()"<<std::endl;
        }

    // Copy constructor
    public:
        template<class TCRTP0, class T0> inline NArray(const AbstractArray<TCRTP0, T0, TSIZE> &rhs) : AbstractArray<NArray<T, TSIZE>, T, TSIZE>(rhs)
        {
            std::cout<<"NArray::NArray(const AbstractArray<TCRTP0, T0, TSIZE> &rhs)"<<std::endl;
        }

    // Initializer list constructor
    public:
        template<class T0> inline NArray(const std::initializer_list<T0>& rhs) : AbstractArray<NArray<T, TSIZE>, T, TSIZE>(rhs)
        {
            std::cout<<"NArray::NArray(const std::initializer_list<T0>& rhs)"<<std::endl;
        }

    // Destructor
    public:
        inline ~NArray()
        {
            std::cout<<"NArray::~NArray()"<<std::endl;
        }
};

// Vector class
template<class T, unsigned int TSIZE> class NVector : public  AbstractArray<NVector<T, TSIZE>, T, TSIZE>
{
    // Constructor
    public:
        inline NVector() : AbstractArray<NVector<T, TSIZE>, T, TSIZE>()
        {
            std::cout<<"NVector::NVector()"<<std::endl;
        }

    // Copy constructor
    public:
        template<class TCRTP0, class T0> inline NVector(const AbstractArray<TCRTP0, T0, TSIZE> &rhs) : AbstractArray<NVector<T, TSIZE>, T, TSIZE>(rhs)
        {
            std::cout<<"NVector::NVector(const AbstractArray<TCRTP0, T0, TSIZE> &rhs)"<<std::endl;
        }

    // Initializer list constructor
    public:
        template<class T0> inline NVector(const std::initializer_list<T0>& rhs) : AbstractArray<NVector<T, TSIZE>, T, TSIZE>(rhs)
        {
            std::cout<<"NVector::NVector(const std::initializer_list<T0>& rhs)"<<std::endl;
        }

    // Destructor
    public:
        inline ~NVector()
        {
            std::cout<<"NVector::~NVector()"<<std::endl;
        }
};

// Main
int main()
{
    NArray<double, 3> a1({1., 2., 3.});
    std::cout<<std::endl;
    NArray<int, 3> a2({4., 5., 6.});
    std::cout<<std::endl;
    NArray<double, 3> a3({7., 8., 9.});
    std::cout<<std::endl;
    NVector<double, 3> v1({11., 12., 13.});
    std::cout<<std::endl;
    NVector<double, 3> v2({14., 15., 16.});
    std::cout<<std::endl;
    NVector<double, 3> v3({17., 18., 19.});
    std::cout<<std::endl;
    NVector<int, 3> v4({20., 21., 22.});
    std::cout<<std::endl;
    a1 = a2;
    std::cout<<std::endl;
    std::cout<<"TEST -> a1 = "<<a1[0]<<" "<<a1[1]<<" "<<a1[2]<<std::endl;
    std::cout<<std::endl;
    v1 = a2;
    std::cout<<std::endl;
    std::cout<<"TEST -> v1 = "<<v1[0]<<" "<<v1[1]<<" "<<v1[2]<<std::endl;
    std::cout<<std::endl;
    v1 += a2;
    std::cout<<std::endl;
    std::cout<<"TEST -> v1 = "<<v1[0]<<" "<<v1[1]<<" "<<v1[2]<<std::endl;
    std::cout<<std::endl;
    v1 = a3+a3;
    std::cout<<std::endl;
    std::cout<<"TEST -> v1 = "<<v1[0]<<" "<<v1[1]<<" "<<v1[2]<<std::endl;
    std::cout<<std::endl;
    //v2 = v3+v4; // <- This line does not work : "error : no match for "operator+" in "v3+v4"
    std::cout<<std::endl;
    return 0;
}

如何解决问题?还有一个问题要问专家:您认为这种编码运算符的方式是否有效,或者您是否考虑过一些可以提高代码质量的修改?在我开始使用 CRTP 修改我当前的实现之前,任何建议都将不胜感激。

非常感谢你 !

4

1 回答 1

1

您可以使用以下方法修复使其编译:

v2 = v3.operator+<int> (v4);

代替

v2 = v3+v4; // <- This line does not work : "error : no match for 

我已经明确告诉编译器那T0是什么int。我已经通过使用.operator+<int>.

但是,可能还有另一个微妙的问题。在 的定义中operator+,我们看到它需要 aconst AbstractArray<TCRTP, T0, TSIZE>& rhs作为参数。在这种情况下T0 == intTSIZE == 3,这很好;但问题是它TCRTP仍然被定义为什么NVector<double,3>时候应该是NVector<int,3>

总之,可以显式地告诉编译器模板参数。但这提出了两个问题:

  • 即使您手动指定类型,它们是正确的类型吗?如果你有一个独特的TCRTPTCRTP0用于operator+=
  • 我们如何自动推断(正确的)类型?
于 2012-08-01T13:13:23.213 回答