3

我在我的 C++ 项目中使用 GNU 科学库。为了方便起见,我想透明地包装gsl_vector*在一个 C++ 类中(以添加一堆特定于域的函数并简化接口)。但我对如何处理感到困惑const gsl_vector*。让我解释。让我从这个简约的包装器开始。

class Vector {
  gsl_vector* vector_;
public:
  Vector(gsl_vector* vector): vector_(vector) {}
  double& operator()(int i) {
    return *gsl_vector_ptr(vector_, i);
  }
};

进一步假设我有两个功能。一是定义如下:

int f(Vector& x) {
  \\ do some math, e.g. x(0) = 0.0;
  return 0;
}

另一种是必须使用 GSL 类型的回调函数,定义如下:

int gsl_f(gsl_vector* x) {
  Vector xx(x);
  return f(xx);
}

这工作正常。现在,假设回调有一个常量签名:

int gsl_f(const gsl_vector* x);

然后我可以相应地重新定义我的Vector类和我的f功能:

class Vector {
  const gsl_vector* vector_;
public:
  Vector(const gsl_vector* vector): vector_(vector) {}
  const double& operator()(int i) const {
    return *gsl_vector_const_ptr(vector_, i);
  }
};

int f(const Vector& x) {
  \\ do some math 
  return 0;
}

也有效。现在,我希望我的包装类适合这两种情况。例如,我希望能够执行以下操作,同时保持 const 的安全性

int f(const Vector& x, Vector& y) {
  \\ do some math 
  return 0;
}

int gsl_f(const gsl_vector* x, gsl_vector* y) {
  Vector yy(y);
  return f(x, yy);
}

我可以通过使用Vector带有两个指针(const 和 non-const)的 a 来做到这一点,并记住它是从 const 成员还是非常量成员初始化的。我的问题是,我可以在没有运行时检查的情况下做到这一点吗?毕竟,所有信息在编译时就在那里。

4

3 回答 3

0

结合这两个类应该可以按预期工作,您尝试过吗?

class Vector {
  gsl_vector* vector_;
public:
  Vector(gsl_vector* vector): vector_(vector) {}

  const double& operator()(int i) const {
    return *gsl_vector_ptr(vector_, i);
  }
  double& operator()(int i) {
    return *gsl_vector_ptr(vector_, i);
  }

  operator const_Vector()
  { 
    return const_Vector(vector_);
  }

};


class const_Vector {
  const gsl_vector* vector_;
public:
  const_Vector(const gsl_vector* vector): vector_(vector) {}

  const double& operator()(int i) const {
    return *gsl_vector_ptr(vector_, i);
  }
};

函数签名需要这样看:

int f(const_Vector& x, Vector& y) {
  \\ do some math 
  return 0;
}

这遵循类似迭代器和 const_iterator 的方案。

也许你有一种情况,这是行不通的,。您应该发布这种情况,我们可以尝试解决它。

于 2012-09-07T12:05:40.563 回答
0

建议(不是很好,但应该可行):

class Vector { 
  gsl_vector* vector_;
  const gsl_vector* const_vector_; 
public: 
  Vector(const gsl_vector* vector): vector_(nullptr), const_vector_(vector) {} 
  Vector(gsl_vector* vector): vector_(vector), const_vector_(vector) {}
  const double& operator()(int i) const { 
    return *gsl_vector_ptr(const_vector_, i); 
  } 
  double& operator () (int i) {
    return *gsl_vector_ptr(vector_, i);
  }
}; 

第二种可能:

class Vector { 
private:
  gsl_vector* vector_;

  Vector(gsl_vector* vector): vector_(vector) {}

public:
  static const Vector* Create (const gsl_vector* vector) {
     return new Vector (const_cast<Vector *> vector);
  }

  static Vector* Create (gsl_vector* vector) {
     return new Vector (vector);
  }

  const double& operator()(int i) const { 
    return *gsl_vector_ptr(vector_, i); 
  } 
  double& operator () (int i) {
    return *gsl_vector_ptr(vector_, i);
  }
}; 
于 2012-09-07T14:15:23.263 回答
0

您还可以使用某种带有数据指针的继承。进一步 - 模板可用于创建重载函数,根据输入指针类型返回一个或第二个版本。

class JSONChannelFullConfigConst:
        public JSONObjectRenderer {
public:
    JSONChannelFullConfigConst(const uint8_t * channel_id,
                               const sensors_single_channel_config_t * cfg) :
                    j_channel_id(channel_id),
                    j_cfg(cfg) {

    }

private:
    const uint8_t * const j_channel_id;
    const sensors_single_channel_config_t * const j_cfg;
    void renderFields(rlf::UcOstreamBase& os) const;
    public:
    uint8_t getId() const {
        return *j_channel_id;
    }
};

class JSONChannelFullConfig:
        public JSONChannelFullConfigConst,
        public JSONObjectParser {
public:
    JSONChannelFullConfig(uint8_t * channel_id, sensors_single_channel_config_t * cfg) :
                    JSONChannelFullConfigConst(channel_id, cfg),
                    j_channel_id(channel_id),
                    j_cfg(cfg) {

    }
    void setId(uint8_t id) {
        *j_channel_id = id;
    }
private:
    uint8_t * const j_channel_id;
    sensors_single_channel_config_t * const j_cfg;

    virtual bool parseNameValuePair(const char * name, rlf::UcIstream & value);
};
于 2012-11-23T14:31:21.127 回答