3

私はC++にかなり慣れていないので、許してください。しかし、演算子のあいまいさに関して問題があります。デスクトップでコンパイルされたコードについては、コンパイラ固有だと思います。しかし、私のラップトップではコンパイルできません。何が悪いのかはわかっていると思いますが、それを回避するためのエレガントな方法はわかりません。明らかな間違いがある場合はお知らせください。とにかく、これが私がやろうとしていることです:

私はVector4と呼ばれる独自のベクトルクラスを作成しました。これは次のようになります。

class Vector4
{
 private:
   GLfloat vector[4];
 ...
}

次に、問題を引き起こしているこれらの演算子があります。

operator GLfloat* () { return vector; }

operator const GLfloat* () const { return vector; }

GLfloat& operator [] (const size_t i) { return vector[i]; }

const GLfloat& operator [] (const size_t i) const { return vector[i]; }

Vector4クラスのインスタンスをglVertex3fvに渡すことができるように、変換演算子があります。明らかな理由で添え字を付けています。ただし、Vector4の添え字を含む呼び出しは、コンパイラーにとってあいまいになります。

enum {x, y, z, w}
Vector4 v(1.0, 2.0, 3.0, 4.0);

glTranslatef(v[x], v[y], v[z]);

候補者は次のとおりです。

candidate 1: const GLfloat& Vector4:: operator[](size_t) const
candidate 2: operator[](const GLfloat*, int) <built-in>

添え字演算子が既にVector4で定義されているのに、なぜ最初にVector4をGLfloat*に変換しようとするのでしょうか。型キャストを伴わない、これを回避する簡単な方法はありますか?私はばかげた間違いをしているだけですか?よろしくお願いします。

4

3 に答える 3

6

これは、「C++テンプレート-完全ガイド」という本で説明されています。これは、operator []がsize_tを取得するためですが、最初にsize_tへの暗黙的な変換を行う必要がある別のタイプを渡します。反対側では、変換演算子も選択でき、返されるポインターは添え字にすることができます。したがって、あいまいさがあります。解決策は、変換演算子を削除することです。ご覧のとおり、問題が発生するだけなので、通常は避ける必要があります。

とをそれぞれ返すメンバー関数を提供beginします。次に、ネイティブのopenGL関数に渡す場合に使用できます。endvectorvector + 4v.begin()

コメントには少し混乱があります。これについての最新の概念を反映するために、この回答を今すぐ更新すると思います。

struct Vector4 {
    // some of container requirements
    typedef GLfloat value_type;
    typedef GLfloat& reference;
    typedef GLfloat const& const_reference;

    typedef GLfloat * iterator;
    typedef GLfloat const * const_iterator;

    typedef std::ptrdiff_t difference_type;
    typedef std::size_t size_type;

    static const size_type static_size = 4;

    // returns iterators to the begin and end
    iterator begin() { return vector; }
    iterator end() { return vector + size(); }

    const_iterator begin() const { return vector; }
    const_iterator end() const { return vector + size(); }

    size_type size() const { return static_size; }
    size_type max_size() const { return static_size; }

    void swap(Vector4 & that) {
        std::swap(*this, that);
    }

    // some of sequences
    reference operator[](size_type t) { return vector[t]; }
    const_reference operator[](size_type t) const { return vector[t]; }

    // specific for us. returns a pointer to the begin of our buffer.
    // compatible with std::vector, std::array and std::string of c++1x
    value_type * data() { return vector; }
    value_type const* data() const { return vector; }

    // comparison stuff for containers
    friend bool operator==(Vector4 const&a, Vector4 const&b) {
        return std::equal(a.begin(), a.end(), b.begin());
    }
    friend bool operator!=(Vector4 const&a, Vector4 const&b) { return !(a == b); }
    friend bool operator<(Vector4 const&a, Vector4 const&b) {
        return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
    }
    friend bool operator> (Vector4 const&a, Vector4 const&b) { return b < a;    }
    friend bool operator<=(Vector4 const&a, Vector4 const&b) { return !(b < a); }
    friend bool operator>=(Vector4 const&a, Vector4 const&b) { return !(a < b); }

private:
    GLfloat vector[4];
}
于 2008-12-21T07:10:31.683 に答える
1

あいまいさを取り除くのは難しすぎます。直接[]アクセス、またはキャストからフロート*とそれに続く配列のインデックス付けとして簡単に解釈できます。

私のアドバイスは、演算子GLfloat*を削除することです。暗黙のキャストをこのようにフロートさせるのは問題を抱えているだけです。フロートに直接アクセスする必要がある場合は、下にある生のフロートへのポインターを返すVector4へのget()(または他の任意の名前)メソッドを作成します。

その他のランダムなアドバイス:独自のベクトルクラスを再発明するのではなく、OpenEXRの一部である「IlmBase」パッケージの優れたものを使用する必要があります

于 2008-12-21T07:09:49.313 に答える
0

「const size_t」を operator[] に渡すのはなぜですか?

于 2008-12-21T07:58:09.747 に答える