2010-10-20 4 views
10

J'essaye de créer une classe de vecteur de bits en C++ pour modéliser du matériel. Dans la plupart des HDL (la description du matériel Langauges) que je connais, des bits spécifiques sont référencés comme ceci:Comment puis-je "remplacer" [] pour accepter deux arguments en C++?

my_vector[bit_position] 

et les sous-vecteurs sont référencés comme ceci:

my_vector[msb:lsb] 

ou

my_vector[msb,lsb] 

Je veux être capable de faire quelque chose de similaire avec ma classe de bit-vector. Est-il possible de dire operator[] pour accepter deux arguments?

Les alternatives que j'ai pris en compte sont les suivants:

  1. en utilisant une méthode range:

    my_vector.range(msb,lsb)

  2. en utilisant une chaîne et l'analyser:

    my_vector["msb:lsb"]

Mais ni l'un ni l'autre n'est attrayant. Le premier, parce qu'il est trop différent de la façon dont il est modélisé en HDL, le second parce que je n'aime pas traiter avec des cordes quand je n'ai pas à le faire, et cela semble inélégant.

Quelle est la meilleure façon de faire cela?

+0

Que pensez-vous de la syntaxe de mon_vector <1,2>? –

+0

@Eric: c'est bien. comment pourrais-je faire cela? Cela ne nécessite-t-il pas une définition de modèle? –

+1

-1 pour la mise en œuvre de choses «cool». Achetez une copie du standard C++ et lisez-le. (par exemple, ISO/CEI 14882: 2003, chapitre 13.5.5: l'opérateur [] doit être une fonction membre non statique avec exactement un paramètre). Vous ne serez pas capable de "simuler" toute la syntaxe de VHDL en C++, alors pourquoi ne pas utiliser les méthodes (je devrais vous donner +1 pour considérer l'alternative 1 :-)). Aussi de bonnes lectures dans ce contexte sont: http://mindprod.com/jgloss/unmain.html et http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.14 –

Répondre

23

La question:

Outre operator() tous les opérateurs ont un arité fixe, ce qui empêche effectivement toute forme de changement

Vous avez alors plusieurs solutions:

  • surcharge operator() à la place: vector(msb, lsb)
  • utiliser deux successives invocations: vector[msb][lsb]
  • surcharge l'opérateur virgule: vector[msb,lsb]

La dernière solution correspond à la syntaxe dont vous avez besoin, mais est un peu subtile:

  • vous devez d'abord soit msb ou lsb pour être d'une coutume type (pour les opérateurs ne peut pas être surchargé sur les built-ins seulement)
  • vous fournissez alors une surcharge de operator, pour ce type, en retournant un objet Range
  • vous fournir enfin une coutume operator[](Range) votre classe

La vraie déception est le premier point: que l'un des msb ou lsb besoin d'être d'un type personnalisé. Cela peut être quelque peu allégé en utilisant Boost.StrongTypedef qui crée un type personnalisé qui imite un existant.

+3

Surcharge de l'opérateur de virgule ... c'est extrêmement inhabituel, et susceptible de trébucher. Voir aussi le point 20 de http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.9 – user9876

+0

@ user9876: en effet, il est inhabituel, je l'ai mentionné pour l'exhaustivité si. J'utiliserais personnellement la deuxième solution (invocations successives) car elle me permet de "mettre en cache" l'objet proxy dans des boucles serrées. –

+1

@ user9876: Dans ce cas, il est probablement moins déroutant, car il n'est utilisé que dans le cadre d'une utilisation spéciale. Bien sûr, si quelqu'un utilise un opérateur de virgule dans l'une des parties d'une instruction 'for', c'est la période de confusion. –

20

un struct simple avec deux membres en tant que paramètre à l'opérateur [] ...

struct pos 
{ 
    int lsb; 
    int msb; 
}; 

pos foo={1,2}; 

my_vector[foo]; 

ou dans la nouvelle norme, je crois que vous pouvez simplement faire:

my_vector[pos{1,2}] 
+3

Même avec l'ancien standard, vous pouvez donner 'pos' un constructeur et écrire' my_vector [pos (1,2)] ', ce qui n'est pas trop mal Dans ce cas, il devrait être appelé 'range', pas' pos', puisque nous extrayons une sous-gamme, ne pas adresser en 2 dimensions –

+0

Ceci est en fait très élégant! –

+0

+1 J'aime cette proposition –

4

La solution habituelle est de surcharger l'opérateur(). Cela vous permet de faire des choses comme my_vector (1, 2).

Les contournements utilisant l'opérateur [] sont possibles, mais comme l'indique Matthieu M., vous avez besoin d'un type personnalisé.

+0

Ne fonctionnera pas à moins que "1" soit d'un type auquel vous pouvez ajouter un opérateur,(). Ce qui n'est pas. –

+0

J'aime votre deuxième alternative ... même si je ne suis pas convaincu que cela fonctionne. –

+1

Ceci est toujours une lecture amusante sur la façon dont vous pouvez abuser de C++ pour atteindre vos propres fins: http://www.xs4all.nl/~weegen/eelis/analogliterals.xhtml – Eric

2

L'opérateur de deux arguments [] n'est pas possible en C++. Les noms de, l'antériorité, l'associativité de, et l'arité des opérateurs est fixé par le langage. 1 Opérateur() peut cependant prendre deux arguments ...

7

Est-il possible de dire à operator[] d'accepter deux arguments?

No.

Il y a deux alternatives communes. L'un est de surcharger operator() à la place. Vous devez ensuite l'appeler en utilisant la syntaxe ().

L'autre est d'avoir un retour operator[] objet proxy pour lequel operator[] est surchargée, aussi. Cela peut être appelé comme des tableaux multidimensionnels en C, avec plusieurs [][] en série.

+1

Je pense que la syntaxe multi-dimensionnelle de tableau est un peu bête dans ce cas, où nous sommes réellement après une sous-gamme. 'myvector [0] [8]' ne veut évidemment pas dire, "les 8 premiers bits de' myvector' "comme le veut le questionneur, donc une fonction serait presque certainement meilleure. –

+0

@Steve. C'est certainement vrai. (Je viens de répondre à la question comme citée, et de toute évidence oublié le contexte.) C'est la raison pour laquelle j'ai voté [la réponse de Nim] (http://stackoverflow.com/questions/3977817/how-can-i-override-to -accept-two-arguments-in-c/3977854 # 3977854) à la place. – sbi

-1

utiliser une langue avec des tranches de tableau à la place? = P

+0

ce serait une option si la base de code sur laquelle je travaille n'était pas en C++ –

+0

C++ a des tranches de tableau comme 'std :: slice', elles ne le font pas fonctionne très bien: vP – Potatoswatter