3

C++ プロジェクトで GNU Scientific Library を使用しています。便宜上、C++ クラスを透過的にラップしたいと思いますgsl_vector*(一連のドメイン固有の関数を追加し、インターフェイスを簡素化するため)。しかし、私はどのように対処するかについて困惑しています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);
  }
};

さらに、2 つの関数があるとします。1 つは次のように定義されます。

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

もう 1 つは、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);
}

const と non-const の 2 つのポインターを持ち、Vectorそれが const または non-const メンバーのどちらから初期化されたかを覚えておくことで、これを行うことができます。私の質問は、実行時チェックなしで実行できますか? 結局、すべての情報はコンパイル時に存在します。

4

3 に答える 3

0

データへのポインタを使用して、ある種の継承を使用することもできます。さらに-テンプレートを使用して、入力ポインターのタイプに応じて1つまたは2番目のバージョンを返すオーバーロードされた関数を作成できます。

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 に答える
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);
  }
}; 

2 番目の可能性:

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 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 に答える