unconventional uses of friend in c++ - c++

I know the general use cases for the friend keyword with regards to encapsulation but one a couple of occasions, I have needed the friend keyword just to "get the job done". These use cases don't make me happy so I'm wondering if there are some alternatives. Here's the first minimal example:
struct Foo{
enum class Bar{
a=1,b=2,c=4
};
// need to tell the compiler of operator| before it gets used
// but it can't be a member function of Foo: so add friend keyword
friend Bar operator|(const Bar& b1, const Bar& b2);
// constructor needs a default value using
// operator| for Bars
Foo( Bar b = Bar::a | Bar::b );
};
// definition of operator|, etc.
Is there any way for the compiler to see the declaration of the operator| for the nested class, inside of interface, before the default values are given at the Foo constructor declaration?
I also sometimes find myself using the friend keyword in defining symmetric operations of nested classes within templates. For example:
template<typename T>
struct A{
struct B{
friend bool operator==(const B& x, const B& y) { return true; }
};
};
The operator== does not require friendship from an encapsulation perspective. But due to operator== not actually being a templated function and the compiler being unable to deduce the types of nested classes within templates, this seems to be the only reasonable "trick" to keep operator== as a free function.
As I said, these choices do work, but I'm wondering if there are better choices/practices out there.

In fact, I would say it's perfectly conventional. While, as mentioned by Evg, hidden friends have special benefits, visible friends are also great to have!
To make this more of an answer, consider for example libstdc++'s implementation of std::unreachable_sentinel_t. This can be returned as the end() of an unbounded "generator range", such as a std::ranges::iota_view{0}. It's very similar to your second example:
struct unreachable_sentinel_t
{
template<weakly_incrementable _It>
friend constexpr bool
operator==(unreachable_sentinel_t, const _It&) noexcept
{ return false; }
};
inline constexpr unreachable_sentinel_t unreachable_sentinel{};
Regular iterators and sentinels are defined as nested classes and also rely on friendship, though their comparison operators typically do need the privileged access. However, even if you could provide an out-of-line definition, an additional benefit of inlining friends in templates is that you don't have to repeat the exact template header, including potentially complicated constraints.
If it helps, in C++ you can think of free functions like these, whether or not they are friends, as being part of the public interface of the classes of their arguments, due to argument-dependent lookup. As such, even if you don't technically need the privilege of friendship, granting it does not break encapsulation.
As long as you're aware of the nuance of hidden friendship, just use friend if it gets the job done!

Related

Why is it recommended to declare functions as "friends" in operator overloading [duplicate]

This question already has answers here:
Operator overloading : member function vs. non-member function?
(2 answers)
Closed 8 years ago.
I have read this at many places which recommend of using "friend" while overload operators but no body explained it clearly as to why it is really needed? Why can not we declare them as plain member function? Any shortcoming?
Googled this but did not get any clear answer.
Sometimes you can't declare operator overload as a member function, like in IO operator<< and operator>>. The first parameter of these functions has to be ostream or istream, which are library classes and you can't extend them, declaring such functions as friend gives them access to private variables of your class.
Using friend means it's a nonmember friend function.
For improving encapsulation by minimizing dependencies, it's better to declare nonmember nonfriend functions. If it need to access the private/protected member of the class, make it friend. At last, make it a member function.
Here's an algorithm to determine whether a function should be a member and/or friend, from [C++ Coding Standards: 101 Rules, Guidelines, and Best Practices By Herb Sutter, Andrei Alexandrescu](Item 44. Prefer writing nonmember nonfriend functions):
// If you have no choice then you have no choice; make it a member if it must be:
If the function is one of the operators =, ->, [], or (), which must be members:
Make it a member.
// If it can be a nonmember nonfriend, or benefits from being a nonmember friend, do it:
Else if: a) the function needs a different type as its left-hand argument (as do operators >> or <<, for example); or b) it needs type conversions on its leftmost argument; or c) it can be implemented using the class's public interface alone:
Make it a nonmember (and friend if needed in cases a) and b) ).
If it needs to behave virtually:
Add a virtual member function to provide the virtual behavior, and implement the nonmember in terms of that.
Else: Make it a member.
In some case, such as above-mentioned a) and b), you can't achieve them by member function, you have to declare them as nonmember function, and make them friend if need to access the private/protected member of the class.
There are a few reasons people use friend:
sometimes granting friendship is actually reasonable, as the public API shouldn't expose some members than need to be compared
it's convenient for a lazy programmer to grant access to all the private and protected data members, ensuring you can write the operator implementation without needing to go back to grant access later or use a less obvious/direct public function (that's NOT a good reason, just a lazy one)
you can define the operator function inside the class, where any template parameters, typedefs, constants etc. don't need to be explicitly qualified as they would in the surrounding [namespace] scope. That's considerably simpler for those new to C++.
e.g.:
template <typename T>
struct X
{
friend bool operator==(const X& lhs, const X& rhs) { ... }
};
...vs...
...struct X as above without ==...
template <typename T>
bool operator==(const X<T>& lhs, const X<T>& rhs) { ... }
in a two-birds-with-one-stone scoop, it makes the function nominally inline, avoiding One Definition Rule complications
Only the first reason above is a compelling functional reason for making the operator a friend, rather than making it a non-member function, given the lesser encapsulation and correspondingly higher maintenance burden involved.
There are excellent reasons though to prefer either a friend or non-friend non-member function to a member function, as an implicit constructor can then kick in to allow the operator to work with one instance of the class and another value from which a second instance can be constructed:
struct X { X(int); };
bool operator==(const X& lhs, const X& rhs);
x == 3; // ok for member or non-member operator==
3 == x; // only works for non-member operator== after implicit X(3) for lhs
You are listing two options only for overloaded operator, while actually there are three:
global function, not friend
member function
global function, friend of the class
You did not list the first one, and yet it is the recommended one. If you can define an operator in terms of existing class public interface, define it as global function outside the class. In this way you do not extend the class public interface without need, minimizing the number of functions with access to the class private members.
What to do if the operator needs to access the class private members? Then you have two options - member function or a friend global function. From those two member function is preferable because it is cleaner. However, in some cases it is not possible to define an overloaded operator as the member function. If the object of your class is right-hand argument to two-argument operator, then global function is the only choice.
I assume that we are comparing global-scope friends that are defined in class and non-friends.
The reasons that the former is sometimes preferred are that such functions...
... need access to the data members for the operation to be performed. This can also be done by loosening encapsulation by providing the data through public getters, but that's not always desired.
... shall only be found via ADL to avoid pollution of some namespaces and overload candidate sets. (Only friend functions that are defined in the class they are a friend of satisfy this!)
Moreover, a minor goodie is that for class templates, it's easier to define a global function that operates on specializations inside them since we avoid making the function a template. Also the function is implicitly inline. All this shortens the code, but is no primary reason.
If your implementation followed proper data encapsulation then you might not exposed your data variables to outside world and all data members will be declared as private.
But using operator overloading most of the times you will be accessing the data members , please note it here you will be accessing the data members outside your class. So to provide access to the data members outside your class it is advised to declare the operator overloaded function as friend.
But this might not be required for unary operators , as it will operate on the data members of the particular class in which it is called.
Let me know if you need any examples for your understanding.
There are serious advantages to non-member functions when dealing with operators.
Most operators are binary (take two arguments) and somewhat symmetrical, and with a member operator they only work if *this is the left-hand side argument. So you need to use a non-member operator.
The friend pattern both gives the operator full access to the class (and, operators are usually intimate enough that this isn't harmful), and it makes it invisible outside of ADL. In addition, there are significant advantages if it is a template class.
Invisible outside of ADL lets you do crazy stuff like this:
struct bob {
template<class Lhs, class Rhs>
friend bob operator+( Lhs&&, Rhs&& ) { /* implementation */ }
}
here our operator+ is a template that seemingly matches anything. Except because it can only be found via ADL on bob, it will only be matched if it is used on at least one bob object. This technique can let you pick up on rvalue/lvalue overloads, do SFINAE testing on properties of types, etc.
Another advantage with template types is that the operator ends up not being a template function. look here:
template<class T>
struct X {};
template<class T>
bool operator==( X<T>, X<T> ) { return true; }
template<class T>
struct Y {
friend bool operator==( Y, Y ) { return true; }
};
struct A {
template<class T>
operator X<T>() const { return {}; }
};
struct B {
template<class T>
operator Y<T>() const { return {}; }
};
int main() {
A a;
X<int> x;
B b;
Y<int> y;
b == y; // <-- works!
a == x; // <-- fails to compile!
}
X<T> has a template operator==, while Y<T> has a friend operator==. The template version must pattern-match both arguments to be a X<T>, or it fails. So when I pass in an X<T> and a type convertible to X<T>, it fails to compile, as pattern matching does not do user defined conversions.
On the other hand, Y<T>'s operator== is not a template function. So when b == y is called, it is found (via ADL on y), then b is tested to see if it can convert to a y (it can be), and the call succeeds.
template operators with pattern matching are fragile. You can see this problem in the standard library in a few points where an operator is overloaded in ways that prevent conversion from working. Had the operator been declared a friend operator instead of a public free template operator, this problem can be avoided.

Friending classes defined in the std namespace: any guarantees?

This question came up as I answered this question: does the standard allow and make any guarantees about friend-ing standard library classes and/or functions?
In this particular case, the situation the question was whether:
class MyUserDefinedType
{
friend struct std::default_delete<MyUserDefinedType>;
private:
~MyUserDefinedType() { }
}
is guaranteed to allow MyUserDefinedType to be stored in a std::unique_ptr<MyUserDefinedType> or std::shared_ptr<MyUserDefinedType> object with the default deleter.
In general, are classes described in the standard library required to implement their functionality directly, or can they use any arbitrary level of indirection? For example, is it possible that
std::default_delete<MyUserDefinedType> is actually a using alias of a class defined in an inner namespace of std, in which case the friend declaration would be illegal
or
std::default_delete<MyUserDefinedType> calls some other class that actually does the deleting, in which case the friend declaration would not have the desired effect
or something else along those lines?
My guess is that this is UB not guaranteed to work but I am curious if this is addressed specifically by the standard.
This specific example given above works for clang trunk (w/libc++) and GCC 4.7.2 (w/libstdc++), FWIW
is it possible that std::default_delete<MyUserDefinedType> is actually a using alias of a class defined in an inner namespace of std, in which case the friend declaration would be illegal?
No. Per Paragraph 20.7.1.1.2 of the C++11 Standard:
namespace std {
template <class T> struct default_delete {
constexpr default_delete() noexcept = default;
template <class U> default_delete(const default_delete<U>&) noexcept;
void operator()(T*) const;
};
}
The fact that it has to be a class template is explicitly specified. This means it cannot be an alias template. If that was the case, it would also be impossible to specialize it.
is it possible that std::default_delete<MyUserDefinedType> calls some other class that actually does the deleting, in which case the friend declaration would not have the desired effect?
Yes. Nothing in the Standard specifies that the call cannot be done by some internal helper. Per Paragraph 20.1.1.2:
void operator()(T *ptr) const;
3 Effects: calls delete on ptr.
4 Remarks: If T is an incomplete type, the program is ill-formed.
This only specifies what the effect of invoking the call operator on the default_delete<> functor should be, not how this shall be achieved concretely (whether directly inside the body of the call operator, or by delegating the task to some member function of some other class).
In general, are classes described in the standard library required to implement their functionality directly, or can they use any arbitrary level of indirection?
In general an implementation may indirect as much as it wants. Have e.g. a look at the implementations of standard containers and their iterators - or just use them wrong and see which templates are involved from the error messages. However, since default_delete is nothing magic, that should be a one-liner, you can expect it to do the work itself, but it's not guaranteed.
My guess is that this is UB but I am curious if this is addressed specifically by the standard.
It's not UB, it's just unspecified.
You could be sure if you just specialized default_delete<MyUserDefinedType> (it is allowed to specialize standard libraray templates), but I would not do that.
I would not use friendship at all, especially not if it comes to templates that have not been specialized. Consider this:
//your code
class MyUserDefinedType
{
friend struct std::default_delete<MyUserDefinedType>; //for deletion
private:
int veryPrivateData;
~MyUserDefinedType() { }
};
//evil colleague's code:
namespace std {
//we may specialize std-templates for UDTs...
template<>
struct default_delete<MyUserDefinedType>
{
constexpr default_delete() noexcept = default;
template <class U> default_delete(const default_delete<U>&) noexcept {}
void operator()(T* pt) const { delete pt; }
//sneaky...
void access(MyUserDefinedType& mudt, int i) const
{ mudt.veryPrivateData = i; }
};
}
void somewhere_deep_in_the_code()
{
MyUserDefinedType& myUDT = /*something...*/;
std::default_delete<MyUserDefinedType>().access(myUDT, 42); //tricked you!
}
Friends can do anything to you. Choose them with caution. In this case, I'd really recommend a custom deleter - assuming it makes any sense making the destructor private but providing access to it via the deleter.

Which C++ operators can not be overloaded without friend function?

Which C++ operators can not be overloaded at all without friend function?
You only need a friend declaration if:
You define the operator as a standalone function outside the class, and
The implementation needs to use private functions or variables.
Otherwise, you can implement any operator without a friend declaration. To make this a little bit more concrete... one can define various operators both inside and outside of a class*:
// Implementing operator+ inside a class:
class T {
public:
// ...
T operator+(const T& other) const { return add(other); }
// ...
};
// Implementing operator+ outside a class:
class T {
// ...
};
T operator+(const T& a, const T& b) { return a.add(b); }
If, in the example above, the "add" function were private, then there would need to be a friend declaration in the latter example in order for operator+ to use it. However, if "add" is public, then there is no need to use "friend" in that example. Friend is only used when granting access is needed.
*There are cases where an operator cannot be defined inside a class (e.g. if you don't have control over the code of that class, but would still like to provide a definition where that type is on the left-hand side, anyway). In those cases, the same statement regarding friend declarations still holds true: a friend declaration is only needed for access purposes. As long as the implementation of the operator function relies only on public functions and variables, a friend declaration is not needed.
The operators where the left-hand-side operand is not the class itself. For example cout << somtething can be achieved via defining a std::ostream& operator<<(std::ostream& lhs, Something const & rhs); function, and marking them as friend inside the class.
EDIT: Friending is not needed, ever. But it can make things simpler.
The only reason to use friend function is to access the private(including protected) member variable and functions.
You never need a friend function. If you don't want the operator to
be a member (usually the case for binary operators which do not modify
their operands), there's no requirement for it to be a friend. There
are two reasons one might make it a friend, however:
in order to access private data members, and
in order to define it in the class body (even though it is not a
member), so that ADL will find it
The second reason mainly applies to templates, but it's common to define
operators like + and - in a template base class, in terms of +=
and -=, so this is the most common case.
Operator overloading and friendship are orthogonal concepts. You need to declare a function (any function) friend whenever it needs access to a private member of the type, so if you overload an operator as a function that is not a member and that implementation needs access to the private members, then it should be friend.
Note that in general it is better not to declare friends, as that is the highest coupling relationship in the language, so whenever possible you should implement even free function overloads of operators in terms of the public interface of your type (allowing you to change the implementation of the type without having to rewrite the operators). In some cases the recommendation would be to implement operatorX as a free function in terms of operatorX= implemented as a public member function (more on operator overloading here)
There is an specific corner case, with class templates, where you might want to declare a free function operator as a friend of the template just to be able to define it inside the template class, even if it does not need access to private members:
template <typename T>
class X {
int m_data;
public:
int get_value() const { return m_data; }
friend std::ostream& operator<<( std::ostream& o, X const & x ) {
return o << x.get_value();
}
};
This has the advantage that you define a single non-templated function as a friend in a simple straightforward way. To move the definition outside of the class template, you would have to make it a template and the syntax becomes more cumbersome.
You need to use a friend function when this is not the left-hand-side, or alternatively, where this needs to be implicitly converted.
Edit: And, of course, if you actually need the friend part as well as the free function part.
operators [] -> =
Must be a member functions.
Other binary operators acceptable for overloading can be write in function form or in memeber-function form.
Operators acceptable for overloading is all unary and binary C++ operators except
: . :: sizeof typeid ?

C++ Templates vs. Aggregation

Consider the following piece of code:
class B {
private:
// some data members
public:
friend bool operator==(const B&,const B&);
friend ostream& operator<<(ostream&,const B&);
// some other methods
};
template <typename T=B>
class A {
private:
// some data members
vector<vector<T> > vvlist;
public:
// some other methods
};
My requirement is that the type T that is passed as type parameter must provide definitions for the operator== and the operator<< methods. I do not want to enforce any other restrictions on T.
How can I do this?
One way that I can think of is to Create an Abstract class say "Z" that declares these two methods.
and then write
vector<vector<Z> > vvlist;
and NOT have class A as a template.
Is there a better way to do this?
It happens automatically.
If your code calls the operators == and <<, then the code simply won't compile if the class is passed a type that doesn't define these operators.
It is essentially duck-typing. If it looks like a duck, and quacks like a duck, then it is a duck. It doesn't matter whether it implements an IDuck interface, as long as it exposes the functionality you try to use.
It seems like you are looking for a concept check library. See what Boost has to offer: Boost Concept Check Library. That link also has a good explanation what concepts are. Quote:
A concept is a set of requirements
(valid expressions, associated types,
semantic invariants, complexity
guarantees, etc.) that a type must
fulfill to be correctly used as
arguments in a call to a generic
algorithm
In your question, the concept is "type T must provide operator== and operator<<".
You can write a private method in A that would test required stuff on T in compile time.
void TestReq(T x, T y)
{
if (x==y)
cout << x;
}
This way even plain integers would pass and work.

Review: reusable safe_bool implementation

Trying to find a "simple to use" safe_bool idiom/implementation, I've ended up with my own.
Q: Is this implementation correct?
template <typename T>
class safe_bool
{
protected:
typedef void (safe_bool::*bool_type)() const;
bool_type to_bool_type(bool b) const
{ return b ? &safe_bool<T>::safe_bool_true : 0; }
private:
void safe_bool_true() const {}
private:
bool operator ==(safe_bool<T> const & rhs);
bool operator !=(safe_bool<T> const & rhs);
};
to be used like this:
struct A : public safe_bool<A>
{
// operator bool() const { return true; }
operator bool_type() const { return to_bool_type(true); }
};
The only addition to existing base classes would be to_bool_type, but I hope I've got everything else correct, too.
The test cases I used (VC9) can be found here.
The downsides I see in implementation: bool_type and to_bool_type are visible in derived classes, which might not appease to everyone. Also, using the wrong template argument (e.g. class B : public safe_bool<A> introduced during copy-and-paste) will go unnoticed.
The “wrong template argument” problem you mentioned is almost completely eliminated by the static_cast in the wikibooks.org solution (“for testability without virtual functions”) cited by #Terry Mahaffey. The only thing I can see wrong with their solution is the separate safe_bool_base class, which will suppress the empty base optimization when it appears in multiple base classes (or elements in a compressed_pair). Personally, I'd move that implementation back up into the template.
Using a pointer to a member function as the bool alias is idiomatic, as you're doing here.
Your implementation looks correct for what is there, but slightly incomplete. See http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool
IMO safe_bool falls into the category of things which do more harm than good; ie the complexity and confusion introduced by this idiom along with the mental effort needed to understand it are greater than the intial problem it is intending to solve.