2008-12-21 45 views
3

原谅我,因为我对C++相当陌生,但我在运算符模糊性方面遇到了一些麻烦。我认为它是编译器特定的,用于在我的桌面上编译的代码。但是,它无法在我的笔记本电脑上编译。我想我知道发生了什么问题,但我没有看到它的优雅方式。如果我犯了一个明显的错误,请让我知道。总之,这里就是我想要做的事: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转化为GLfloat *第一时标操作已经在Vector4上定义了?有没有简单的解决方法,不涉及类型转换?我只是犯了一个愚蠢的错误?感谢您提前提供任何帮助。

+0

应用于size_t参数的const不是必需的 - 它毫无意义。然而,这是良性的,并且不会影响您的问题。 – 2008-12-21 06:54:07

+0

你应该告诉我们你正在使用什么编译器.... – SoapBox 2008-12-21 07:05:39

+0

我无法检查我目前在桌面上使用的是哪种编译器,但我在我的笔记本电脑上使用的编译器(它给了我错误)是g ++ 4.3.2。我使用Eclipse,默认情况下有这些标志: -O0 -g3 -Wall -c -fmessage-length = 0 – Scott 2008-12-21 07:15:06

回答

6

这是本书“C++模板解释部分使用优秀的 - 完全指南”。这是因为你的运算符[]需要size_t,但是你传递了一个不同的类型,首先必须隐式转换为size_t。另一方面,也可以选择转换运算符,然后返回的指针可以是下标。所以有歧义。解决方案是放弃转换运算符。正如你所看到的,它们通常应该避免,因为它们只是引入问题。

提供一个beginend成员函数,分别返回vectorvector + 4。如果你想传递给本地的openGL函数,那么你可以使用v.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]; 
} 
1

摆脱歧义是太难了。它可以很容易地将其解释为直接[]访问,或者后继数组索引的强制转换。

我的建议是放弃操作员GLfloat *。这只是要求让隐式强制转换以这种方式浮动。如果您必须直接访问浮动元素,请向Vector4创建一个get()(或您选择的其他名称)方法,该方法返回一个指向下方的原始浮动元素的指针。

其他随机的建议是:而不是彻底改造自己的向量类,我们应当在“IlmBase”包是OpenEXR

+0

谢谢!我不知道转换操作员是一个坏主意。我想因为我对C++很陌生,所以还没有被他们烧掉。我意识到必须有大量的矢量和矩阵类,但是我真的决定让自己成为更多的练习。 – Scott 2008-12-21 07:36:50

0

你为什么要向operator []传递一个“const size_t”?