Question

Will it be possible and/or useful to define an operator "" (...) as a friend function?

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

I am thinking about "useful" especially, because of the rule that operator "" shall be defined in a namespace only -- not the least because identifiers beginning with _ are reserved in global namespace. Is this friend breaking this rule here? So, there would be no benefit with this not-quite encapsulation, right?

Was it helpful?

Solution

The Standard addresses this directly in the only place it mentions any restrictions on the declarations of user-defined literals, §13.5.8/2:

A declaration whose declarator-id is a literal-operator-id shall be a declaration of a namespace-scope function or function template (it could be a friend function (11.3)), an explicit instantiation or specialization of a function template, or a using-declaration (7.3.3).

If the friend is also declared at namespace scope, then there is no distinction between definition in class or namespace scope. Note that there is no requirement for definition at namespace scope, which your question as currently worded asserts.

If not declared at namespace scope, since it cannot be found by ADL, the friend could be used privately inside the class where it is scope by regular unqualified name lookup. This is the only way of declaring a literal operator which is not an external interface.

If the friend is defined inside a class template, then two instantiations of the template will generate two identically-named functions at namespace scope, which collide even though they are both invisible outside the class scope.

OTHER TIPS

In case it helps with syntax, here is how I declare a friend user-defined literal operator in a class, where the operator itself is in a namespace:

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;

};

Users pull in the operator with a using namespace literals; statement only if they want it. (And, actually, all of this is in a parent namespace, but you get the idea).

According to the standard, yes, a friend declaration should be legal. By the way, the name is fine for user code since it starts with an underscore even in global namespace.

The friend declaration would allow the operator to access class-private data.

I am beginning to question the usefulness of friend literal operators. Because the user-defined operators can only have a few argument lists there is no way to put the class in the arguments. So there is now way for argument dependent look-up to find the right function. Am I right?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top