C++ variable membre alias?
Je suis sûr que cela est possible, parce que je suis assez sûr que je l'ai vu faire. Je pense que c'est génial, mais je serai heureux d'accepter des réponses du genre "c'est une très mauvaise idée parce que ____".
Dire que nous avons une base struct.
struct vertex
{
float x, y, z;
};
Maintenant, je veux mettre en œuvre des alias sur ces variables.
vertex pos;
vertex col;
vertex arr;
pos.x = 0.0f; pos.y = 0.5f; pos.z = 1.0f;
col.r = 0.0f; col.g = 0.5f; col.b = 1.0f;
arr[0] = 0.0f; arr[1] = 0.5f; arr[2] = 1.0f;
Idéalement, la troisième syntaxe serait impossible de distinguer à partir d'un tableau. C'est, si j'ai envoyé arr
comme un paramètre de référence à une fonction attend un tableau de float dans lequel il stocke les données (par exemple, de nombreux OpenGL glGet
fonctions), ça marcherait bien.
Qu'en pensez-vous? Possible? Possible, mais stupide?
OriginalL'auteur mcccclean | 2009-01-30
Vous devez vous connecter pour publier un commentaire.
Ce que je voudrais faire, c'est de faire des accesseurs:
Bon début, cependant, cela implique d'avoir à appeler un memberfunction afin d'accéder à un champ. Vous pouvez effectuer les opérations suivantes (ouais, avoir des références en tant que membres n'est pas quelque chose que vous faites habituellement, mais dans certains cas, il peut être pratique): struct Sommet { Vertex(): r(valeurs[0]), g(valeurs[1]), b(valeurs[2]), x(valeurs[0]), y(valeurs[1]), z(valeurs[2]) {} float& r; float& g; float& b; float& x; float& y; float& z; private: float valeurs[3]; };
Ces méthodes sont écrits en ligne, de sorte que le compilateur doit optimiser l'appel de fonction membre et accéder à la variable directement, donc c'est un non-problème. J'ai compilé ton code sous Visual Studio 2008 et il était de 24 octets plus grande en raison de la période de six références que vous avez ajoutés à la classe. Si l'intention était de Vertex pour être un léger classé qui serait passé par valeur, ce n'est pas ce que vous voulez.
OriginalL'auteur Ray Hidayat
Utilisation d'un syndicat?
Je ne le recommande pas - il conduire à la confusion.
Ajouté:
Comme indiqué par Adrian, dans sa réponse, cette union avec anonyme, les membres de la structure n'est pas pris en charge par l'ISO C++. Il fonctionne sous GNU G++ (avec des plaintes au sujet de ne pas être pris en charge lorsque vous mettez"
-Wall -ansi -pedantic
'). Il rappelle la pré-pré-standard C jours (pre-K&R 1ère Éd.), lorsque l'élément de structure de noms devaient être unique au sein de toutes les structures, et vous pouvez utiliser contracté notations pour arriver à un décalage au sein de la structure, et vous pouvez utiliser les noms de membres d'autres types de structure - une forme d'anarchie. Au moment où j'ai commencé à l'aide de C (il y a longtemps, mais post-K&R1), qui était déjà à l'historique d'utilisation.La notation montré avec anonyme, membres de l'union (pour les deux structures) est pris en charge par C11 (ISO/IEC 9899:2011), mais pas par les versions antérieures de la norme. L'article 9.5 de l'ISO/IEC 14882:2011 (C++11) prévoit pour les syndicats, mais GNU
g++
(4.9.1) n'accepte pas le code qui s'affiche avec-pedantic
, d'identifier les "warning: ISO C++ prohibits anonymous structs [-Wpedantic]
".Depuis que l'idée sera source de confusion, je ne suis pas particulièrement inquiet qu'il n'est pas standard; je ne voudrais pas utiliser le mécanisme de cette tâche (et je serais réticent à l'idée de l'utilisation anonyme des structures dans une union, même si c'est utile).
Une préoccupation a été soulevée:
C'est une union de trois éléments; les trois éléments de commencer à la même adresse. Les deux premiers sont des structures contenant 3 valeurs flottantes. Il n'y a pas d'héritage, et il n'y a pas de fonctions virtuelles pour donner différentes mises en page, etc. Les structures seront établies avec les trois éléments contigus (dans la pratique, même si la norme permet de remplissage). Le tableau commence également à la même adresse, et faisant l'objet d'aucune rembourrage " dans les structures, les éléments se chevauchent les deux structures. Je ne vois vraiment pas qu'il y aurait un problème.
Serait techniquement illégal.
Un autre problème avec lui est qu'il conduit à l'aliasing, ce qui inhibe l'optimisation du compilateur. Si la performance est importante, qui pourrait être un problème.
OriginalL'auteur Jonathan Leffler
Sans nom imbriqués les structures dans une union qui ne sont pas standard C++. Toutefois, ceci devrait fonctionner:
EDIT: UN peu plus d'informations. La structure utilise un tableau de 3 pointeur vers les données-membres d'accéder aux données dans le surchargés [] des opérateurs.
La ligne "typedef float Vertex::* const vert" signifie que le vert est un pointeur vers un float membre du Vertex struct. [3] signifie que c'est un tableau de 3 de ces. Dans la surcharge de l'opérateur[], ce tableau est indexé et que le pointeur vers les données-membre est déréférencé et la valeur retournée.
En outre, cette méthode devrait fonctionner indépendamment de l'emballage questions - le compilateur est libre de pad le Sommet de la structure cependant, il aime et il va toujours très bien fonctionner. Un anonyme de l'union sera de rencontrer des problèmes si les flotteurs sont emballés différemment.
pourquoi est v tableau statique?
Parce que cela permet d'économiser la mémoire, il n'y a aucune raison pour qu'il soit par exemple. Pointeur vers les données-ont besoin d'une instance de l'objet avant qu'ils peuvent être utilisés - un (float Vertex::*) pointant vers le Sommet::x (par exemple) peut être utilisé avec n'importe quel Sommet d'instance pour obtenir cette instance x de membre.
Qu'est-ce->*v[i]; compiler, je me demande? Est-il le résultat dans une double indirection, ou ne le compilateur tranquillement inline le pointeur de membre et jusqu'à la fin avec un seul indexé charge de l'op?
OriginalL'auteur Adrian
Vous pouvez l'obtenir avec un syndicat comme les autres l'ont mentionné. La surcharge de couleur et de position sur la même structure comme ceci est peut-être pas une bonne idée ( par exemple, l'ajout de deux couleurs signifie habituellement que vous voulez de saturer à 1,0, alors que l'ajout de vecteurs qui se passe de façon linéaire ), mais en y ajoutant un float[] au-dessus d'eux comme ça, c'est parfaitement bien, et un bien acceptée de l'échange des données avec GL/DirectX/etc.
Je vous recommande d'éviter de faire référence à la même membre par un alias différent dans la même portée de la fonction, bien que, parce que cela va vous conduire dans un méchant matériel de décrochage appelé une charge-hit-store. En particulier, évitez si vous le pouvez:
OriginalL'auteur Crashworks
Références?
memcpy
la structure (ce qui n'est pas trop rare si vous voulez l'utiliser comme POD des aides, en n'utilisant pas virtuals)OriginalL'auteur strager
Je ne suis pas sûr de savoir si j'ai compris correctement à la question. Mais il semble que vous avez besoin de surcharger l'opérateur[] pour fournir de tableau comme l'accès à votre struct/classe. Voir l'exemple mentionné ici: La surcharge d'opérateur
OriginalL'auteur Naveen
Structure suivante aura le comportement demandé:
OriginalL'auteur Kresimir
Je suppose que vous pouvez faire un peu de macro de la magie pour obtenir ce que vous voulez.
Mais ce sera moche. Pourquoi voulez-vous utiliser la même structure, un sommet pour les 3 différents types? Pourquoi ne pouvez-vous pas à la notion de classe pour la couleur?
Aussi garder à l'esprit que le sommet et la couleur ne sont pas les mêmes. Si vous modifiez quelque chose sur un sommet, qui va affecter la couleur aussi, si vous avez la même classe pour les deux.
OriginalL'auteur chappar
Mauvaise idée à mon avis, au moins pour l'exemple donné: l'inconvénient est que, pour à peu près n'importe quelle solution à cela, vous allez probablement être en mesure de céder librement "rvb" instances vers/à partir de "xyz" instances, ce qui est probablement rarement sensible ou de corriger. c'est à dire vous risque d'abandonner certaines de sécurité de type.
Personnellement, pour l'exemple que vous donnez, j'avais sous-classe rvb et xyz types à partir d'une base de
boost::array<float,3>
ou similaire. De sorte que les deux d'entre eux héritent de l'opérateur[], peuvent être transmis à des fonctions attend tableaux, et ont passé plus de sécurité de type à des choses attend de couleurs coordonnées. C'est souvent que vous voulez traiter d'un xyz ou rgb, comme un tableau, mais rares que vous voulez traiter d'un xyz comme une rvb ou vice-versa. (rvb EST-UN tableau: OK. xyz EST-UN tableau: OK. rgb EST UN xyz ???? Je ne le pense pas!)Bien sûr, cela signifie que l'accès à l'x,y,z & r,g,b doit être par accesseur (transfert approprié
operator[](...)
) plutôt que de s'adresser directement aux états. (Vous auriez besoin de C#propriétés pour ça).OriginalL'auteur timday
J'ai un modèle et deux Vecteur de classes ci-dessous, un fou, un de sain d'esprit. Le modèle met en œuvre un simple fixé au moment de la compilation tableau de valeurs. Il est conçu pour les sous-classement et utilise un protégé de la variable de matrice de vous éviter d'avoir à sauter à travers des cerceaux pour accéder au tableau. (Certaines personnes pourraient ne pas aimer une telle conception. Je dis, si votre sous-classes appelez vos opérateurs surchargés, couplage pourrait être une bonne idée.)
La classe folle vous permet d'avoir des variables de membre appelé x, y, z et il agit comme un tableau pour les appels à glGetFloatV. Le sain d'esprit, on n'aura fonctions d'accesseur x(), y(), z() et travaille toujours avec glGetFloatV. Vous pouvez utiliser une classe comme base pour d'autres objets vectoriels que vous risquez de passer à la librairie OpenGL. Bien que les classes ci-dessous sont spécifiques à points, vous pouvez évidemment faire un rechercher/remplacer pour les transformer en une couleur rgb classes.
La classe folle est fou parce que le coût du sucre syntaxique vec.x à la place de vec.x() est de 3 variables de référence. Qui pourrait prendre beaucoup de place dans une grande application. L'utilisation la plus simple sane version.
OriginalL'auteur jmucchiello
Vous pouvez essayer d'ajouter des références à des variables, comme ceci:
Mais votre structure devient plus grand (à partir de 12 octets à 40 octets).
À utiliser [] sur elle, utiliser la surcharge de l'opérateur[], comme mentionné précédemment.
OriginalL'auteur klew
Juste un avertissement sur l'utilisation de référence des membres de pointage à la valeur des membres. Vous avez besoin de définir un constructeur de copie (et, éventuellement, également opérateur d'affectation), si jamais vous copiez un objet (comme le transfert par valeur). Le constructeur de copie par défaut vous laisse avec une copie dont la référence des membres de la point de la valeur des membres de l'objet d'origine, pas ceux du nouvel objet. Ce n'est certainement pas quelque chose que vous voulez.
Considérant que vous avez également jusqu'à la fin avec de plus gros objets, comme l'a déjà souligné, je pense que l'utilisation des méthodes accesseur est préféré au cours de référence de membres.
OriginalL'auteur