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
Related
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.
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 have two simple class that I made just to understand how friend class works. I am confused as to why this doesn't compile and also would the Linear class have access to the struct inside Queues class?
Linear.h
template<typename k, typename v >
class Linear
{
public:
//Can I create a instance of Queues here if the code did compile?
private:
};
Linear.cpp
#include "Linear.h"
Queues.h
#include "Linear.h"
template<typename k, typename v >
class Linear;
template<typename x>
class Queues
{
public:
private:
struct Nodes{
int n;
};
//Does this mean I am giving Linear class access to all of my Queues class variable or is it the opposite ?
friend class Linear<k,v>;
};
Queues.cpp
#include"Queues.h"
My errors are
Queues.h:15: error: `k' was not declared in this scope
Queues.h:15: error: `v' was not declared in this scope
Queues.h:15: error: template argument 1 is invalid
Queues.h:15: error: template argument 2 is invalid
Queues.h:15: error: friend declaration does not name a class or function
To answer your initial question:
the friend keyword inside a class let the friend function or class access otherwise private field of the class where the friend constraint is declared.
See this page for a thorough explanation of this language feature.
Regarding the compilation errors in your code:
In this line:
friend class Linear<k,v>;
ask yourself, what is k, where is it defined? Same for v.
Basically, a template is not a class, it's a syntactic construct letting you define a "class of class", meaning that for the template:
template <typename T>
class C { /* ... */ };
you don't have yet a class, but something that will let you define class if you provide it a proper typename. Within the template the typename T is defined, and can be used in place as if it were a real type.
In the following code snippets:
template <typename U>
class C2 {
C<U> x;
/* ... */
};
you define another template, which when instantiated with a given typename will contain an instance of the template C with the same typename. The typename U in the line C<U> x; of the code above, is defined by the including template. However, in your code, k and v don't have such a definition, either in the template where they are being used, or at the top level.
In the same spirit, the following template:
template <typename U>
class C2 {
friend class C<U>;
/* ... */
};
when instantiated, will have the instance of the class template C (again with the same parameter U) as a friend. As far as I know, It is not possible to have class template instances be friend with a given class, for all possible parameters combinations (The C++ language doesn't support existential types yet).
You could, for instance, write something like:
template<typename x>
class Queues
{
public:
private:
struct Nodes{
int x;
};
friend class Linear<x,x>;
};
to restrict the friendliness of Linear to only the instance of that template with x and x, or something like this:
template<typename x,typename k, typename v>
class Queues
{
public:
private:
struct Nodes{
int x;
};
friend class Linear<k,v>;
};
If you want to allow k and v to be defined ad lib.
Your problem is with templates not with friend classes in that code.
Friend just means that restrictions against access to private and protected are removed for that class. As if the word private in the class was public, basically.
Do try to submit code with one problem and which you understand all but one thing.
I have a two template class, templateClass1 and templateClass2. I want to use private variables and methods of templateClass1 in templateClass2. Is it possible to do so by using friend keyword in c++ ?
Sumit
I know this post is probably dead, but for other people who stumble upon this...
templateClass1.h
template <class T> class templateClass2; // forward declare
template <typename T>
class templateClass1 {
friend templateClass2<T>;
};
templateClass2.h
template <class T> class templateClass1; // forward declare
template <typename T>
class templateClass2 {
friend templateClass1;
}
It is possible to have a friends of any type, but a template is not a type until its template arguments have been supplied. So in general you would have to have a specialization for each full type you wish to be friends with. This will push you toward attempting to pass the type to be friend as a template parameter, but you can not supply a template type that will be friended.
for ex. this is illegal
template <class T>
class A
{
friend class T;
};
with those stipulations it makes it very difficult to do anything meaning full with templates and friendedness.
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?