请原谅我,因为我对C ++很新,但我在操作员歧义方面遇到了一些麻烦。对于我桌面上编译的代码,我认为它是特定于编译器的。但是,它无法在我的笔记本电脑上编译。我想我知道出了什么问题,但我看不到它的优雅方式。如果我犯了一个明显的错误,请告诉我。无论如何,这就是我想要做的事情:
我创建了自己的Vector4类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 *?有没有一个简单的方法来解决这个问题?我只是犯了一个愚蠢的错误?感谢您提前提供任何帮助。
答案 0 :(得分:6)
“C ++模板 - 完整指南”一书对此进行了解释。这是因为你的operator []接受size_t,但是你传递了一个不同的类型,它首先必须经过隐式转换为size_t。另一方面,也可以选择转换运算符,然后返回的指针可以是下标。所以有歧义。解决方案是删除转换运算符。通常应该避免它们,因为它们只会引入问题,如你所见。
提供begin
和end
成员函数,分别返回vector
和vector + 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 :(得分:1)
摆脱歧义太难了。它可以很容易地将其解释为direct [] access,或者cast-to-float *,然后是数组索引。
我的建议是放弃运营商GLfloat *。这只是要求隐式转换以这种方式浮动的麻烦。如果必须直接访问浮点数,请向Vector4创建一个get()(或您选择的其他名称)方法,该方法返回指向下方原始浮点数的指针。
其他随机建议:您应该使用属于OpenEXR
一部分的“IlmBase”包中的优秀类型,而不是重新发明自己的向量类。答案 2 :(得分:0)
为什么要将“const size_t”传递给operator []?