현재 연구를위한 작은 수학 벡터 및 행렬 및 일부 특수 함수를 다루기 위해 라이브러리를 작성하고 있습니다. 현재 CRTP 트릭을 테스트 중입니다. 다음 코드는 마지막 행에서 오류를 생성하고 그 이유를 알 수 없습니다. 이유는 알 수 없습니다 :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로 현재 구현을 수정하기 전에 모든 조언을 부탁드립니다.
대단히 감사합니다!
기본 클래스 ('NVector'->'AbstractArray') 로의 변환이'operator +'에 대한 템플릿 인자 공제에서 고려되고 있습니까? 나는 그렇게해서는 안된다. – Andrey
좋은 질문 Andrey. 하지만 내 솔루션에 문제가 있다고 생각합니다. –
당신의 "But"는 아주 좋은 지적입니다. "template 인라인 AbstractArray :: type, TSIZE> 연산자 + (const AbstractArray & rhs) const"는 다음과 같이 정의를 변경합니다. 잘! 현재 구현에서 문제가 아닌 (매우 안전하지 않은 것 같은) 것이 있습니까, 아니면 모두 괜찮습니까 (내 라이브러리는 기본적으로 이것에 의존 할 것입니다)? –
Vincent