Est-il possible de surcharger l' []
opérateur deux fois? Pour permettre, quelque chose comme ceci: function[3][3]
(comme dans un tableau à deux dimensions).
Si c'est possible, j'aimerais voir un exemple de code.
c++
operator-overloading
icepopo
la source
la source
operator()(int, int)
place ...std::vector
avec un constructeur de plage: stackoverflow.com/a/25405865/610351using array2d = std::array<std::array<int, 3>, 3>;
Réponses:
Vous pouvez surcharger
operator[]
pour renvoyer un objet sur lequel vous pouvez utiliser àoperator[]
nouveau pour obtenir un résultat.Ensuite, vous pouvez l'utiliser comme:
Ceci n'est qu'un exemple simple, vous voudriez ajouter un tas de vérifications de limites et d'autres choses, mais vous voyez l'idée.
la source
Proxy::operator[]
devrait revenirint&
non seulementint
std::vector<std::vector<int>>
pour éviter les memleak et les comportements étranges sur la copie.multi_array
etextent_gen
sont de bons exemples de cette technique. boost.org/doc/libs/1_57_0/libs/multi_array/doc/…const ArrayOfArrays arr; arr[3][5] = 42;
sera en mesure de passer la compilation et des changementsarr[3][5]
, ce qui est quelque peu différente de ce que l' attente des utilisateurs quiarr
estconst
.Proxy::operator[]
ne renvoie pas de référence dans ce code (en supposant que votre commentaire ne soit pas une réponse à Ryan Haining). Plus important encore, siarr
est constoperator[]
ne peut pas être utilisé. Vous auriez à définir une version const, et bien sûr vous la feriez revenirconst Proxy
. AlorsProxy
lui-même aurait des méthodes const et non-const. Et puis votre exemple ne se compilerait toujours pas, et le programmeur serait heureux que tout va bien dans l'univers. =)Une expression
x[y][z]
nécessite quex[y]
s'évalue à un objetd
qui prend en charged[z]
.Cela signifie qu'il
x[y]
devrait s'agir d'un objet avec unoperator[]
qui s'évalue en un "objet proxy" qui prend également en charge unoperator[]
.C'est la seule façon de les enchaîner.
Vous pouvez également surcharger
operator()
pour prendre plusieurs arguments, de sorte que vous puissiez appelermyObject(x,y)
.la source
Pour un tableau à deux dimensions, en particulier, vous pourriez vous en sortir avec une seule surcharge d'opérateur [] qui renvoie un pointeur vers le premier élément de chaque ligne.
Vous pouvez ensuite utiliser l'opérateur d'indexation intégré pour accéder à chaque élément de la ligne.
la source
C'est possible si vous retournez une sorte de classe proxy lors du premier [] appel. Cependant, il existe une autre option: vous pouvez surcharger operator () qui peut accepter n'importe quel nombre d'arguments (
function(3,3)
).la source
Une approche consiste à utiliser
std::pair<int,int>
:Bien sûr, vous pouvez
typedef
lepair<int,int>
la source
nValue = theArray[{2,3}];
Vous pouvez utiliser un objet proxy, quelque chose comme ceci:
la source
Ça va être génial si vous pouvez me faire savoir ce que
function
,function[x]
etfunction[x][y]
êtes. Mais de toute façon permettez-moi de le considérer comme un objet déclaré quelque part comme(Parce que vous avez dit que c'est une surcharge d'opérateurs, je pense que vous ne serez pas intéressé par un tableau comme
SomeClass function[16][32];
)Il en
function
va de même pour une instance de typeSomeClass
. Ensuite, recherchez la déclaration deSomeClass
pour le type de retour deoperator[]
surcharge, tout commeReturnType operator[](ParamType);
Ensuite,
function[x]
aura le typeReturnType
. Encore une fois, recherchezReturnType
laoperator[]
surcharge. S'il existe une telle méthode, vous pouvez alors utiliser l'expressionfunction[x][y]
.Note, à la différence
function(x, y)
,function[x][y]
sont 2 appels distincts. Il est donc difficile pour le compilateur ou le runtime de garantir l'atomicité sauf si vous utilisez un verrou dans le contexte. Un exemple similaire est, libc dit queprintf
c'est atomique alors que les appels successifs auoperator<<
flux de sortie surchargé ne le sont pas. Une déclaration commepeut avoir un problème dans une application multi-thread, mais quelque chose comme
c'est bien.
la source
la source
J'ai trouvé ma propre solution simple à cela.
la source
Cela vous permet de prendre un lambda et de produire un indexeur (avec
[]
support).Supposons que vous ayez un
operator()
qui prend en charge le passage des deux coordonnées à onxe comme deux arguments. Maintenant, le[][]
support d' écriture est juste:Et.. Voila. Aucune classe personnalisée requise.
la source
Si, au lieu de dire un [x] [y], vous souhaitez dire un [{x, y}], vous pouvez faire comme ceci:
la source
Il est possible de surcharger plusieurs [] en utilisant un gestionnaire de modèle spécialisé. Juste pour montrer comment cela fonctionne:
Et maintenant, la définition de
SubscriptHandler<ClassType,ArgType,RetType,N>
pour faire fonctionner le code précédent. Cela montre seulement comment cela peut être fait. Cette solution est optimale ni sans bogue (pas threadsafe par exemple).la source
Avec a
std::vector<std::vector<type*>>
, vous pouvez créer le vecteur intérieur à l'aide d'un opérateur d'entrée personnalisé qui itère sur vos données et renvoie un pointeur vers chaque donnée.Par exemple:
Exemple en direct
Cette solution a l'avantage de vous fournir un véritable conteneur STL, vous pouvez donc utiliser des boucles for spéciales, des algorithmes STL, etc.
Cependant, il crée des vecteurs de pointeurs, donc si vous utilisez de petites structures de données comme celle-ci, vous pouvez directement copier le contenu à l'intérieur du tableau.
la source
Exemple de code:
la source
vector <vector <T>> ou T ** n'est requis que lorsque vous avez des lignes de longueur variable et bien trop inefficaces en termes d'utilisation de mémoire / d'allocations si vous avez besoin d'un tableau rectangulaire, envisagez de faire des maths à la place! voir la méthode at ():
la source
En utilisant C ++ 11 et la bibliothèque standard, vous pouvez créer un très beau tableau à deux dimensions en une seule ligne de code:
En décidant que la matrice interne représente les lignes, vous accédez à la matrice avec une
myMatrix[y][x]
syntaxe:Et vous pouvez utiliser à distance
for
pour la sortie:(Décider des
array
colonnes de représentation internes permettrait unefoo[x][y]
syntaxe, mais vous devrez utiliser desfor(;;)
boucles plus maladroites pour afficher la sortie.)la source
Mes 5 cents.
Je savais intuitivement que je devais faire beaucoup de code passe-partout.
C'est pourquoi, au lieu de operator [], j'ai fait un opérateur surchargé (int, int). Puis en résultat final, au lieu de m [1] [2], j'ai fait m (1,2)
Je sais que c'est différent, mais c'est toujours très intuitif et ressemble à un script mathématique.
la source
La solution la plus courte et la plus simple:
la source