Ambigüedad del operador C++
opengl operators (3)
¿Por qué está pasando un operador "const size_t" to []?
Perdóname, porque soy bastante nuevo en C ++, pero estoy teniendo problemas con la ambigüedad del operador. Creo que es específico del compilador para el código compilado en mi escritorio. Sin embargo, no se puede compilar en mi computadora portátil. Creo que sé lo que está pasando mal, pero no veo una manera elegante de evitarlo. Por favor, avíseme si estoy cometiendo un error obvio. De todos modos, esto es lo que estoy tratando de hacer:
He creado mi propia clase vectorial llamada Vector4 que se ve más o menos así:
class Vector4
{
private:
GLfloat vector[4];
...
}
Luego tengo estos operadores, que están causando el problema:
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]; }
Tengo el operador de conversión para poder pasar una instancia de mi clase Vector4 a glVertex3fv, y tengo una suscripción por razones obvias. Sin embargo, las llamadas que implican la suscripción de Vector4 se vuelven ambiguas para el compilador:
enum {x, y, z, w}
Vector4 v(1.0, 2.0, 3.0, 4.0);
glTranslatef(v[x], v[y], v[z]);
Aquí están los candidatos:
candidate 1: const GLfloat& Vector4:: operator[](size_t) const
candidate 2: operator[](const GLfloat*, int) <built-in>
¿Por qué trataría de convertir mi Vector4 en un GLfloat * primero cuando el operador de subíndice ya está definido en Vector4? ¿Hay una manera simple de evitar esto? ¿Estoy cometiendo un error tonto? Gracias por cualquier ayuda de antemano.
Es muy difícil deshacerse de la ambigüedad. Podría interpretarlo fácilmente como el acceso directo [], o cast-to-float * seguido de la indexación de matrices.
Mi consejo es dejar caer al operador GLfloat *. Es solo pedir problemas tener moldes implícitos para flotar de esta manera. Si debe acceder a los flotadores directamente, haga un método get () (u otro nombre de su elección) para Vector4 que devuelve un puntero a los flotantes crudos que se encuentran debajo.
Otro consejo al azar: en lugar de reinventar sus propias clases de vectores, debe usar las excelentes en el paquete "IlmBase" que es parte de OpenEXR
Esto se explica en el libro "Plantillas C ++: la guía completa". Es porque su operador [] toma size_t, pero pasa un tipo diferente que primero tiene que pasar por una conversión implícita a size_t. Por otro lado, también se puede elegir el operador de conversión, y luego el puntero devuelto puede ser un subíndice. Entonces está la ambigüedad. La solución es soltar el operador de conversión. Por lo general, deben evitarse ya que solo presentan problemas, como puede ver.
Proporcione una función de miembro de begin
y end
que devuelva vector
y vector + 4
respectivamente. Luego puede usar v.begin()
si desea pasar a funciones nativas de OpenGL.
Hay un poco de confusión en los comentarios. Creo que actualizaré esta respuesta ahora para reflejar el concepto más reciente de esto.
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];
}