C++ 具有特定于枚举的实现和共享功能(CRTP)的类模板

C++ 具有特定于枚举的实现和共享功能(CRTP)的类模板,c++,C++,我想设计一个Matrix类,它允许指定内存管理的方法,即 Matrix<Allocator::vector, int> mv(2, 2); Matrix<Allocator::unique_pointer, int> mu(2, 2); mv(1, 1) = 1; mu(1, 2) = 1; 不幸的是,编译器抱怨 ./matrix.hpp:100:34: error: out-of-line definition of 'at' does not match any

我想设计一个
Matrix
类,它允许指定内存管理的方法,即

Matrix<Allocator::vector, int> mv(2, 2);
Matrix<Allocator::unique_pointer, int> mu(2, 2);

mv(1, 1) = 1;
mu(1, 2) = 1;
不幸的是,编译器抱怨

./matrix.hpp:100:34: error: out-of-line definition of 'at' does not match any declaration in 'Matrix<linalg::Allocator::vector,
      type-parameter-0-0>'
T& Matrix<Allocator::vector, T>::at(size_t i, size_t j) {
  ^
./matrix.hpp:103:20: error: use of undeclared identifier 'rows'
  return data_[i * rows() + j];
/matrix.hpp:100:34:错误:“at”的行外定义与“matrix”中的任何声明都不匹配
T&Matrix::at(尺寸i,尺寸j){
^
./matrix.hpp:103:20:错误:使用未声明的标识符“行”
返回数据_ui*rows()+j];
我认为错误源于

template <typename T>
class Matrix<Allocator::vector, T> : public MatrixBase<T> {
 private:
  std::vector<T> data_;
};
模板
类矩阵:公共矩阵库{
私人:
std::矢量数据;
};

如何解决此问题?

将定义移到内部将解决此问题。此问题是由于作用域

template <typename T>
class Matrix<Allocator::vector, T> : public MatrixBase<T> {
public: // or private:
    T& at(size_t i, size_t j) {
        return data_[i * MatrixBase<T>::rows() + j];
    }
private:
    std::vector<T> data_;
};

或者您可以在
C
中重新声明它,因此它将在
C
的范围内。

将定义移到内部将解决此问题。此问题是由于作用域

template <typename T>
class Matrix<Allocator::vector, T> : public MatrixBase<T> {
public: // or private:
    T& at(size_t i, size_t j) {
        return data_[i * MatrixBase<T>::rows() + j];
    }
private:
    std::vector<T> data_;
};

或者您可以在
C
中重新声明它,这样它将在
C
的范围内。

我已经修复了您的代码。给您:

using dim_t = std::pair<size_t, size_t>;

enum class Allocator { vector, raw_pointer, unique_pointer };

template <typename T>
class MatrixBase {
 public:
  MatrixBase() : MatrixBase(0, 0){};
  MatrixBase(size_t m, size_t n) : dim_(m, n){};

  size_t rows() const;

  virtual T& at(size_t i, size_t j);

 private:
  dim_t dim_;
};

template <typename T>
size_t MatrixBase<T>::rows() const {
  return dim_.first;
}

template <Allocator A, typename T>
class Matrix : public MatrixBase<T> {};

template <typename T>
class Matrix<Allocator::vector, T> : public MatrixBase<T> {
    public:
        T &at(size_t i, size_t j);
    private:
        std::vector<T> data_;
};

template <typename T>
T& Matrix<Allocator::vector, T>::at(size_t i, size_t j) {
  return data_[i * this->rows() + j];
}

template <typename T>
class Matrix<Allocator::unique_pointer, T> : public MatrixBase<T> {
    public:
        T &at(size_t i, size_t j);
    private:
        std::unique_ptr<T[]> data_;
};

template <typename T>
T& Matrix<Allocator::unique_pointer, T>::at(size_t i, size_t j) {
  return data_[i * this->rows() + j];
}
使用dim\u t=std::pair;
枚举类分配器{向量,原始指针,唯一指针};
模板
类矩阵基{
公众:
MatrixBase():MatrixBase(0,0){};
MatrixBase(size_t m,size_t n):dim_(m,n){};
行大小()常量;
虚拟T&at(尺寸i、尺寸j);
私人:
昏暗的;
};
模板
大小矩阵基::行()常量{
首先返回dim;
}
模板
类矩阵:公共矩阵基{};
模板
类矩阵:公共矩阵库{
公众:
T&at(尺寸i、尺寸j);
私人:
std::矢量数据;
};
模板
T&Matrix::at(尺寸i,尺寸j){
返回数据_ui*this->rows()+j];
}
模板
类矩阵:公共矩阵库{
公众:
T&at(尺寸i、尺寸j);
私人:
std::唯一的ptr数据;
};
模板
T&Matrix::at(尺寸i,尺寸j){
返回数据_ui*this->rows()+j];
}

首先,如果重写某个方法,则必须在派生类中声明它。其次,
rows()
函数在默认情况下无法作为成员解析。

我已修复了您的代码。给您:

using dim_t = std::pair<size_t, size_t>;

enum class Allocator { vector, raw_pointer, unique_pointer };

template <typename T>
class MatrixBase {
 public:
  MatrixBase() : MatrixBase(0, 0){};
  MatrixBase(size_t m, size_t n) : dim_(m, n){};

  size_t rows() const;

  virtual T& at(size_t i, size_t j);

 private:
  dim_t dim_;
};

template <typename T>
size_t MatrixBase<T>::rows() const {
  return dim_.first;
}

template <Allocator A, typename T>
class Matrix : public MatrixBase<T> {};

template <typename T>
class Matrix<Allocator::vector, T> : public MatrixBase<T> {
    public:
        T &at(size_t i, size_t j);
    private:
        std::vector<T> data_;
};

template <typename T>
T& Matrix<Allocator::vector, T>::at(size_t i, size_t j) {
  return data_[i * this->rows() + j];
}

template <typename T>
class Matrix<Allocator::unique_pointer, T> : public MatrixBase<T> {
    public:
        T &at(size_t i, size_t j);
    private:
        std::unique_ptr<T[]> data_;
};

template <typename T>
T& Matrix<Allocator::unique_pointer, T>::at(size_t i, size_t j) {
  return data_[i * this->rows() + j];
}
使用dim\u t=std::pair;
枚举类分配器{向量,原始指针,唯一指针};
模板
类矩阵基{
公众:
MatrixBase():MatrixBase(0,0){};
MatrixBase(size_t m,size_t n):dim_(m,n){};
行大小()常量;
虚拟T&at(尺寸i、尺寸j);
私人:
昏暗的;
};
模板
大小矩阵基::行()常量{
首先返回dim;
}
模板
类矩阵:公共矩阵基{};
模板
类矩阵:公共矩阵库{
公众:
T&at(尺寸i、尺寸j);
私人:
std::矢量数据;
};
模板
T&Matrix::at(尺寸i,尺寸j){
返回数据_ui*this->rows()+j];
}
模板
类矩阵:公共矩阵库{
公众:
T&at(尺寸i、尺寸j);
私人:
std::唯一的ptr数据;
};
模板
T&Matrix::at(尺寸i,尺寸j){
返回数据_ui*this->rows()+j];
}

首先,如果重写方法,则必须在派生类中声明它函数在默认情况下无法作为成员解析。

这是一个非法返回类型:
T&Matrix
@Viatorus Fixed请提供一个。@BartekBanachewicz Doneth这是一个非法返回类型:
T&Matrix
@Viatorus Fixed请提供一个。@BartekBanachewicz Done为什么需要
这个->
表示它只是nec如果存在歧义,但我没有看到任何命名conflict@bodokaiser看看这个:您不必在派生类中声明重写方法。这是错误的。我的回答表明了这一点。为什么需要
this->
?说明只有在存在歧义的情况下才需要,但我看不到任何命名conflict@bodokaiser看看这个第一:您不必在派生类中声明重写方法。这是错误的。我的回答表明了这一点。