I recently came across a c++ piece of code where a class is made friend to itself. As I have read on different forums a class is already a friend to itself. So I was wondering if there is a specific reason why one would want to make a class friend to itself explicitly.
Another question would be, what's the reason in making a class a friend of itself?
Maybe someone with a lot of experience can clarify this topic.
Here is the code example, to illustrate my question:
template < typename T>
class Foo: public T
{
protected:
template < typename U>
friend class Foo;
}
There's no point indeed to make a class a friend to itself, except if it is a template class. For example the following code makes sense:
template <class T>
class A
{
template<class U>
friend class A;
}
An STL example is the std::_Ptr_base which is the base class for std::shared_ptr and std::weak_ptr.
It is not making the class a friend of itself, it is making all classes of that template a friend to all others. So A<Foo> is a friend of A<Bar> which is a different class.
I am surprised the syntax is as you print it and not template<typename U> friend class A<U>; but that is what it actually means.
Related
Is it possible to make friend of a class, all possible variants of a class-template?
Just to clarify, for example, something like this:
class A
{ friend template B; } // syntactic error yeah
So any B<X> variant could manipulate any protected attribute of A.
A is an small and simple class with a lot of friends who manipulate its attributes. Just one of then need to be a template. I know that I can do this:
template <class T>
class A
{ friend class B<T>; }
But so I would have to change my code in all the other friends and I would like to avoid it.
You may define a friend template class like that:
class A{
template<typename T>
friend class B;
};
That would make every specialization of class B a friend of class A. I've had a similar question that had the opposite goal: to restrict some specializations: Friend template function instantiations that match parameter
I know this title is a bit confusing but a diagram will probably help.
in one file:
#ifndef ...
#def ...
#includes (including OListiterator.h>
template <class T>
class OList;
template <class T>
Class OListiterator{
friend class OList<T>::OList;
typename OList<T>::Node* iiter;
};
function defs;
#endif
in another:
#ifndef ...
#def ...
#includes (one is OList.h)
template<class T>
class OListiterator;
template <class T>
Class OList{
friend class OListiterator<T>::OListiterator;
public:
class Node{
};
//things
};
//functions
#endif
This is what myself and the TA assisting me would have thought would work, but I am thrown the error: Node does not name a type in OList. Does anybody know why/how I can fix this? Let me know if I need to post more.
It looks like there is a dependency here. OList needs OListIterator, and vice versa. The way to solve this is to change your design so this dependency is not needed. Try placing your OListIterator design so it can be used inside the OList.
You need a forward declaration of class OList:
// forward declaration
template <class T>
class OList;
template <class T>
class OListiterator{
friend class OList<T>::OList;
typename OList<T>::Node* iiter;
};
template <class T>
class OList{
friend class OListiterator<T>::OListiterator;
public:
class Node{
};
};
Demo
Note that friend class OList<T>::OList; is equivalent to just friend class OList<T>; because OList<T>::OList is class name injected in scope of OList<T>.
When you name the member Node of OList as a friend, the compiler needs the entire definition of OList to ensure that there is such a member.
The solution would be to break the dependency. Why does a list node need to have access to the list iterator's internals? Seems to me like it should be the other way around.
for example:
template<class T>
class MyClass
{
public:
template<class U>
MyClass<U> doSomething() { return MyClass<U>(); } //can't access private constructor
private:
MyClass() {}
}
Template-voodoo answers and the like are acceptable. What's most important to me is that this class can create and return instances of itself with different template parameters, but that external code cannot call the particular constructor that it is using.
Add the following in MyClass
template<typename Q> friend class MyClass;
MyClass<int> and MyClass<float> resolve to entirely different classes. They know nothing of eachother, and they can't access eachother's privates any more than 2 totally seperate classes. So, the solution is to have every instantiation of MyClass friend every other instantiation so they can all see eachother's privates as if they were the same class.
friend is your friend in this case, as every time you need restricted exceptions from privacy:
class MyClass {
template <class U> friend class MyClass;
....
I am writing a small class, the class is basically a factory for the C class, but I want other classes to be able to access some of the methods.
template<class C>
class CFactory {
public:
friend class C;
};
This should make the fields of CFactory available to the class C, but the compiler thinks otherwise.
I'm getting the following two errors using gcc on a mac.
error: using template type parameter 'C' after 'class'
error: friend declaration does not name a class or function
Can anyone tell me what I'm doing wrong and how to get et right?
Unfortunately, in my understanding, this isn't allowed in current standard.
§7.1.5.3/2 says:
[Note: ... within a class template
with a template type-parameter T, the
declaration
friend class T;
is ill-formed. -end note]
On a related note, this restriction seems to be removed in C++0x
(§11.3/3 in N3290).
Incidentally, MSVC may allow this if we write simply friend T;.
Ise's response is correct -- Comeau's FAQ contains a question concerning this issue in more detail.
However, perhaps you can try an extra template indirection that might work? Something like this:
template <typename T>
struct FriendMaker
{
typedef T Type;
};
template <typename T>
class CFactory
{
public:
friend class FriendMaker<T>::Type;
};
This seems to only work with gcc 4.5.x however so I wouldn't rely on it.
C can be anything - int, double, etc. and they are not classes. In general, this class C is not class. And you cannot have something like:
class A
{
friend class int;
//..
};
One more reason to prefer typename, instead of class when using templates
I need a way to have a single static variable for all kinds of types of my template class
template <class T> class Foo { static Bar foobar;};
Well, the line above will generate a Bar object named foobar for every type T, but this is not what i want, i basically want a way to declare a variable of type Bar, so every object of type Foo has access to the same foobar variable, independent of T.
I tried to use another class to store the private stuff, but that doesnt work, because the standard does not allow stuff like template <class T> friend class Foo<T>;
So the obvious solution (shown below) is to have a global variable Bar foobar, but this obviously violates the information hiding concept (of proper encapsulation):
Bar Foo_DO_NOT_TOUCH_THIS_PLEASE_foobar;
template <class T> class Foo { static Bar& foobar;};
template <class T> Bar& Foo<T>::foobar=Foo_DO_NOT_TOUCH_THIS_PLEASE_foobar;
Ofcourse you can additionally use a detail namespace (thats what i am currently doing), but is there another way which really prohibits users from messing around with your private static variables ?
Additonally this solution will get quite messy when you have to declare lots of static methods in a similar fashion, because you will most likely have to extensivly use the friend keyword like friend RetType Foo_detail::StaticFunc(ArgT1, ArgT2).
And the users wont have a nice interface since they cant use those functions like they are used to Foo<T>::someFunc() but instead they will have to call something like Foo_static::someFunc() (if you use the namespace Foo_static for public static functions).
So is there any other solution which does not break encapsulation, and/or does not introduce lots of syntax overhead ?
EDIT:
based on all your anwsers, i tried following, and it works as intended:
typedef int Bar;
template <class T> class Foo;
class FooBase
{
static Bar foobar;
public:
template <class T> friend class Foo;
};
Bar FooBase::foobar;
template <class T> class Foo : public FooBase
{
public:
using FooBase::foobar;
};
this solution has the benefit, that users can not inherit from FooBase.
Perhaps inherit the static member?
class OneBarForAll
{
protected:
static Bar foobar;
};
template <class T>
class Foo : public OneBarForAll
{
};
Lots of Foo<T>'s will be made, but only one OneBarForAll.
One potential problem with this is that there's nothing stopping other users of the code from inheriting from OneBarForAll and modifying foobar anyway.
Ideally you do want the template friend, as that best describes the access requirements of your design, but C++ does not currently allow that.
The syntax for
template <class T> friend class Foo<T>;
is
template <class T> friend class Foo;
(which means that every instantiation of Foo is a friend of the class you define it in)
So perhaps you can go with the solution you ruled out before.
you could do:
struct Base {
static Foo foo;
};
//init foo here
template<typename T>
struct Derived : Base {
...
};
...
Derived<Bar>::foo;
It works in g++
Why not inherit from a non-template base class?