47 votes

Puis-je créer un nouvel opérateur en C++ et comment ?

Les tableaux de MATLAB prennent en charge les opérations matricielles et les opérations sur les éléments. Par exemple, M*N y M.*N . Il s'agit d'une manière assez intuitive de distinguer les deux opérations différentes. Si je veux mettre en œuvre des opérations similaires en C++, comment puis-je le faire ?

Puis-je créer un nouvel opérateur ? .* aussi ? Si oui, quelqu'un peut-il me donner des conseils ?

32voto

Non, vous ne pouvez pas surcharger op.* :

[C++03 & C++11: 13.5/3]: Les opérateurs suivants ne peuvent pas être surchargés :

. .* :: ?:

28voto

lorro Points 1220

En C++, il existe une liste d'opérateurs prédéfinis, dont la plupart sont surchargeables (.* ne l'est pas). De plus, tout Le nom peut être utilisé comme un opérateur comme :

#include <iostream>

// generic LHSlt holder
template<typename LHS, typename OP>
struct LHSlt {
    LHS lhs_;
};

// declare myop as an operator-like construct
enum { myop };

// parse 'lhs <myop' into LHSlt
template<typename LHS>
LHSlt<LHS, decltype(myop)> operator<(const LHS& lhs, decltype(myop))
{
    return { lhs };
}

// declare (int <myop> int) -> int
int operator>(LHSlt<int, decltype(myop)> lhsof, int rhs)
{
    int& lhs = lhsof.lhs_;
    // here comes your actual implementation
    return (lhs + rhs) * (lhs - rhs);
}

// strictly optional
#define MYOP <myop>

int main() {
    std::cout << (5 <myop> 2) << ' ' << (5 MYOP 2);
}

Clause de non-responsabilité : Ceci, à proprement parler, se traduit par (5 < myop) > 2 qui est LHSlt<int, decltype(myop)>(5) > 2 . Il ne s'agit donc pas d'un nouvel "opérateur", au sens du C++, mais il est utilisé exactement de la même manière, même en termes d'ADL. De plus, si le type est grand, vous voudrez probablement stocker const T& .

Notez que vous pouvez faire cela avec n'importe quel opérateur binaire qui peut être défini en dehors de la classe ; la précédence est basée sur la précédence des deux côtés ( < y > ). Ainsi, vous pouvez avoir par exemple *myop* , +myop+ , <<myop>> , <myop> , |myop| dans cet ordre de préséance.

Si vous voulez une associativité droite, cela devient un peu plus délicat. Vous aurez besoin à la fois d'un support RHS et d'un support LHS (ce dernier étant LHSlt ici) et utiliser les opérateurs environnants de manière à ce que celui de droite ait une plus grande priorité que celui de gauche, par ex. a |myop> b |myop>c est a |myop> (b |myop> c) . Ensuite, vous avez besoin de la fonction pour votre type et votre type de support en tant que lhs.

13voto

Barry Points 45207

Vous ne pouvez pas surcharger .* (voir Réponse de Lightness pour le texte standard), mais, de manière intéressante, vous peut surcharge ->* (de la même manière que vous pouvez surcharger -> mais pas . ). Si cela suffit pour se différencier, alors allez-y :

struct Int {
    int i;

    Int operator*(Int rhs) const { return Int{i * rhs.i}; }
    Int operator->*(Int rhs) const { return Int{i + rhs.i}; }

    friend std::ostream& operator<<(std::ostream& os, Int rhs) {
        return os << "Int(" << rhs.i << ')';
    }
};

int main() {
    Int five{5};
    Int six{6};

    std::cout << (five * six) << ", " << (five ->* six) << '\n';
}

Ça va imprimer Int(30), Int(11) .

9voto

matthias Points 1208

Non, malheureusement vous ne pouvez pas définir de nouveaux opérateurs - vous ne pouvez que surcharger les opérateurs existants (avec quelques exceptions importantes, telles que operator. ). Même dans ce cas, ce n'est généralement qu'une bonne idée de surcharger des opérateurs pour des types qui ont une sémantique existante très claire et non controversée pour un opérateur donné - par exemple, tout type qui se comporte comme un nombre est un bon candidat pour surcharger les opérateurs arithmétiques et de comparaison, mais vous devez vous assurer que operator+ ne permet pas, par exemple, de soustraire deux nombres.

7voto

Francis Cugler Points 480

Les tableaux de MATLAB prennent en charge les opérations matricielles et les opérations sur les éléments. Par exemple, M*N et M.*N. Il s'agit d'une manière assez intuitive de distinguer les deux opérations différentes. Si je veux mettre en œuvre des opérations similaires en C++, comment puis-je le faire ?

Puis-je créer un nouvel opérateur, .*, également ? Si oui, quelqu'un peut-il me donner des conseils ?

En ce qui concerne la première partie, vous pouvez surcharger la plupart des opérateurs et il y en a certains que vous ne pouvez pas surcharger et la liste des opérateurs en C++ sont :

  • Arithmétique

    • + (addition)
    • - (subtraction)
    • * (multiplication)
    • / (division)
    • % (modulus)
  • Par bit :

    • ^ (XOR)
    • | (OR)
    • & (AND)
    • ~ (Complement)
    • << (Shift Left, Insertion to Stream)
    • >> (Shift Right, Extraction from Stream)
  • Affectation

    • = (Assignment)
  • Relationnel

    • == (Equality)
    • != (Inequality)
    • > (Greater-Than)
    • < (Less-Than)
    • >= (Greater-Than Or Equal-To)
    • <= (Less-Than Or Equal-To)
  • Logique

    • ! (NOT)
    • && (AND)
    • || (OR)
  • Attribution des composés

    • += (Addition-Assignment)
    • -= (Subtraction-Assignment)
    • *= (Multiplication-Assignment)
    • /= (Division-Assignment)
    • %= (Modulus-Assignment)
    • &= (AND-Assignment)
    • |= (OR-Assignment)
    • ^= (XOR-Assignment)
    • <<= (Shift-Left Assignment)
    • >>= (Shift-Right Assignment)
  • Incrément - Décrément - Les deux ont 2 formes (préfixe) et (postfixe)

    • ++ (Increment)
    • -- (Decrement)
  • Abécédaire

    • [] (Subscript)
  • Appel de fonction

    • () (Function Call)
  • Adresse, Référence, Pointeur

    • operator&()
    • operator*()
    • operator->()
  • Virgule

    • operator,()
  • Référence du membre

    • operator->()
    • operator->*()
  • Gestion de la mémoire

    • new
    • delete
    • new[]
    • delete[]
  • Conversion

    • operator "type" () const
  • Opérateurs NON modifiables - Opérateurs qui ne peuvent pas être surchargés

    • ?: (Conditional - Ternary)
    • . (Member Selection)
    • .* (Member Selection With Pointer To Member)
    • :: (Scope Resolution)
    • sizeof() (Object Size Information)
    • typeid() (Object Type Information)

La connaissance de cette liste vous aidera donc à répondre à vos questions. Peut-on créer un "nouvel opérateur" en C++ ? Non ! Si vous voulez implémenter des opérations similaires en C++, comment puis-je le faire ?

Vous avez 4 possibilités : Soit surcharger un opérateur existant qui peut l'être, écrire une fonction ou une méthode pour faire le type de calculs que vous voulez effectuer, créer un type de modèle qui fera le travail pour vous, ou le dernier qui est le moins courant à faire mais vous pouvez aussi écrire des macros pour les faire pour vous.

Il existe une bibliothèque d'API mathématique en en-tête seulement qui est utilisée assez fréquemment avec l'API graphique OpenGL et le langage de shaders GLSL d'OpenGL. Cette bibliothèque possède de nombreuses fonctionnalités qui permettent de travailler avec des vecteurs, des matrices, des quaternions, etc., et toutes les fonctions et opérations nécessaires qui peuvent leur être appliquées. Voici le lien vers GLM Vous pouvez jeter un coup d'œil à leur documentation ainsi qu'aux implémentations de leur bibliothèque puisqu'il s'agit d'une bibliothèque ou d'une API à en-tête uniquement. Cela devrait vous donner un aperçu de la façon dont ils ont construit leurs objets Vector et Matrix et des opérations qui peuvent être effectuées sur eux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X