2010-10-20 9 views
10

Estoy tratando de crear una clase de vector de bits en C++ para modelar hardware. En la mayoría de las HDL (descripción hardware Langauges) que conozco, bits específicos son referenciados como esto:¿Cómo puedo "anular" [] para aceptar dos argumentos en C++?

my_vector[bit_position] 

y sub-vectores están referenciados como esto:

my_vector[msb:lsb] 

o

my_vector[msb,lsb] 

Quiero ser capaz de hacer algo similar con mi clase de vector de bits. ¿Hay alguna manera de decirle a operator[] que acepte dos argumentos?

Las alternativas que he consideradas son:

  1. usando un método range:

    my_vector.range(msb,lsb)

  2. utilizando una cadena y analizarlo:

    my_vector["msb:lsb"]

Pero ninguno de ellos es atractivo. El primero, porque es muy diferente de la forma en que está modelado en HDL, el segundo porque no me gusta trabajar con cadenas cuando no es necesario, y parece poco elegante.

¿Cuál es la mejor manera de hacerlo?

+0

¿Cómo te sientes acerca de la sintaxis my_vector <1,2>? –

+0

@Eric: está bien. ¿Cómo voy a hacer eso? ¿Eso no requiere una definición de plantilla? –

+1

-1 para implementar cosas "geniales". Compre una copia del estándar C++ y léalo. (por ejemplo, ISO/IEC 14882: 2003, ch 13.5.5: operator [] debe ser una función miembro no estática con exactamente un parámetro). No podrá "simular" toda la sintaxis de VHDL en C++, entonces, ¿por qué no usar métodos (debería darle +1 para considerar la alternativa 1 :-)). También buenas lecturas en este contexto son: http://mindprod.com/jgloss/unmain.html y http://www.parashift.com/c++faq-lite/coding-standards.html#faq-27.14 –

Respuesta

23

El problema:

Aparte de operator() todos los operadores tienen una aridad fijo, lo que impide de hecho cualquier tipo de cambio

A continuación, tiene varias soluciones:

  • sobrecarga operator() en su lugar: vector(msb, lsb)
  • use dos sucesivos invocaciones: vector[msb][lsb]
  • sobrecargar el operador coma: vector[msb,lsb]

La última solución coincide con la sintaxis que necesita, pero es algo sutil:

  • primero tiene cualquiera msb o lsb a ser de una costumbre tipo (para los operadores no se pueden sobrecargar en las unidades integradas solamente)
  • a continuación, proporciona una sobrecarga de operator, para este tipo, devolviendo un objeto Range
  • que finalmente proporcionan una costumbre operator[](Range) en su clase

El verdadero fastidio es el primer punto: que uno de msb o lsb necesita ser de un tipo personalizado. Esto se puede aliviar un poco usando Boost.StrongTypedef, que crea un tipo personalizado que imita uno existente.

+3

Sobrecargar el operador de coma ... eso es extremadamente inusual, y es probable que haga tropezar a la gente. Ver también el punto 20 de http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.9 – user9876

+0

@ user9876: de hecho es inusual, aunque lo mencioné para completarlo. Yo personalmente usaría la segunda solución (invocaciones sucesivas) ya que me permite "almacenar en caché" el objeto proxy en bucles ajustados. –

+1

@ user9876: en este caso, probablemente sea menos confuso, ya que solo se usa como parte de un uso especial. Por supuesto, si alguien usa un operador de coma en una de las partes de una declaración 'for', es tiempo de confusión. –

20

una estructura simple con dos miembros como parámetro al operador [] ...

struct pos 
{ 
    int lsb; 
    int msb; 
}; 

pos foo={1,2}; 

my_vector[foo]; 

o en la nueva norma, creo que se puede hacer simplemente:

my_vector[pos{1,2}] 
+3

Incluso con el estándar anterior, puede darle a 'pos' un constructor y escribir' my_vector [pos (1,2)] ', lo cual no es tan malo En este caso, debería llamarse 'range', no' pos', ya que estamos extrayendo un sub-rango, no direccionando en 2 dimensiones. –

+0

Esto es realmente muy elegante! –

+0

+1 Me gusta esta proposición. –

4

La solución habitual es anular el operador(). Esto te permite hacer cosas como mi_vector (1, 2).

Es posible trabajar con el operador [], pero como señala Matthieu M., necesita un tipo personalizado para involucrarse.

+0

No funcionará a menos que "1" sea del tipo que puede agregar un operador,() a. Lo cual no es –

+0

Me gusta su segunda alternativa ... aunque no estoy convencido de que funcione. –

+1

Esta es siempre una lectura divertida sobre cómo puede abusar de C++ para lograr sus propios fines: http://www.xs4all.nl/~weegen/eelis/analogliterals.xhtml – Eric

2

El operador de dos argumentos [] no es posible en C++. Los nombres de, la precedencia de, la asociatividad de, y la aridad de los operadores se fija por el idioma. 1 operador(), sin embargo puede tomar dos argumentos ...

7

¿Hay alguna manera de saber operator[] a aceptar dos argumentos?

Hay dos alternativas comunes. Una es sobrecargar operator() en su lugar. Luego debe invocarlo usando la sintaxis ().

La otra es tener operator[] cambio un objeto proxy para el que está sobrecargado operator[], también. Esto se puede invocar como matrices multidimensionales en C, con varios [][] en serie.

+1

Creo que la sintaxis de matriz multidimensional es un poco basura en este caso, donde en realidad estamos detrás de un subintervalo. 'myvector [0] [8]' no significa obviamente, "los primeros 8 bits de' myvector' "como quiere el interrogador, por lo que una función sería casi con toda seguridad mejor. –

+0

@Steve. Esto es ciertamente cierto. (Acabo de responder la pregunta como se cita, y obviamente me olvidé del contexto.) Esa es la razón por la que voté [la respuesta de Nim] (http://stackoverflow.com/questions/3977817/how-can-i-override-to -accept-two-arguments-in-c/3977854 # 3977854) en su lugar. – sbi

-1

¿utiliza un lenguaje con sectores de matriz en su lugar? = P

+0

que sería una opción si la base de código en la que estoy trabajando no estuviera en C++ –

+0

C++ tiene secciones de matriz como 'std :: slice', simplemente no lo hacen funciona muy bien: vP – Potatoswatter

Cuestiones relacionadas