Question

Est-il possible et / ou utile de définir un operator "" (...) en fonction ami?

class Puzzle {
  friend Puzzle operator "" _puzzle(const char*, size_t);
  ...
};
void solve(Puzzle);
int main() {
  solve("oxo,xox"_puzzle);
};

Je pense à « utile » en particulier, en raison de la règle selon laquelle operator "" est définie dans un espace de nom seulement - pas le moins parce que les identificateurs commençant par _ sont réservés à l'espace de noms global. Est-ce friend cette règle ici briser? Donc, il n'y aurait aucun avantage à cette encapsulation pas tout à fait, non?

Était-ce utile?

La solution

La norme aborde ce directement dans le seul endroit où il mentionne aucune restriction sur les déclarations de littéraux définies par l'utilisateur, §13.5.8 / 2:

Une déclaration dont le déclarateur-id est un-Oprateur littéral est une déclaration d'une fonction d'espace de nommage portée ou modèle de fonction ( il pourrait être une fonction ami (11.3) ), explicite instanciation ou spécialisation d'un modèle de fonction, ou une déclaration en utilisant (7.3.3).

Si l'ami est également déclaré à périmètre d'espace de noms, alors il n'y a pas de distinction entre la définition du périmètre de classe ou espace de noms. Notez qu'il n'y a pas d'exigence pour la définition à la portée d'espace de noms, que votre question affirme sa formulation actuelle.

Si non déclarée à périmètre d'espace de noms, car il ne peut pas être trouvé par ADL, l'ami pourrait être utilisé en privé dans la classe où elle est portée par consultation régulière de nom non qualifié. Ceci est la seule façon de déclarer un opérateur littéral qui n'est pas une interface externe.

Si l'ami est défini à l'intérieur d'un modèle de classe, puis deux instanciations du modèle génère deux fonctions de même nom à périmètre d'espace de noms, qui entrent en collision, même si elles sont à la fois invisible hors de la portée de la classe.

Autres conseils

Dans le cas où il aide à la syntaxe, voici comment je déclare un opérateur littéral défini par l'utilisateur ami dans une classe, où l'opérateur lui-même est dans un espace de noms:

class Integer;
namespace literals {
  Integer operator "" _I (const char *);
}

// Infinite precision integer 
class Integer {
  public:

  // Basic constructor & destructor
   Integer ();
  ~Integer ();

... rest of the interface ...

  // Literal operator
  friend Integer literals::operator "" _I (const char *);

  private:

  struct Detail;
  std::unique_ptr<Detail> detail;

};

Les utilisateurs tirent dans l'opérateur avec une instruction using namespace literals; que s'ils le veulent. (Et, en fait, tout cela est dans un espace de noms de parent, mais vous voyez l'idée).

Selon la norme, oui, une déclaration d'ami devrait être légal. Soit dit en passant, le nom est bien pour le code utilisateur car il commence par un trait de soulignement même dans l'espace global.

La déclaration d'ami permettrait à l'opérateur d'accéder à des données de classe privée.

Je commence à remettre en question l'utilité des amis opérateurs littérales. Étant donné que les opérateurs définis par l'utilisateur ne peuvent avoir quelques listes d'arguments il n'y a pas moyen de mettre la classe dans les arguments. Donc, il y a maintenant moyen pour consultation en fonction de l'argument trouver la bonne fonction. Ai-je raison?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top