How to friend template class function - c++

I am trying to declare a specific function in a template class as a friend.
template <class T>
class A
{
// Constructor, destructor, etc..
void update();
}
// This is the function I'm trying to declare as a friend
template <class T> void A<T>::update()
{
// Do stuff, accessing private members of B
}
The class I'm trying to provide friend access:
class B
{
// Here is where I can't figure out how to declare A::update() as a friend function
}
I was able to successfully declare all of A as a friend with:
// Forward declare at top
template class<T>
class A;
// Then inside of class B
template <class T> friend class A;
However, I'm trying to restrict access to B's private/protected scope inside of only A::update().

Try this:
template <class T>
class A
{
void update();
};
class B
{
private:
int asd;
template <class T> friend void A<T>::update();
};
template <class T> void A<T>::update()
{
B test;
test.asd = 2;
}

Related

In C++ can one friend a template class in a non template class for ALL specializations of the template class? [duplicate]

Let's say I'm creating a class for a binary tree, BT, and I have a class which describes an element of the tree, BE, something like
template<class T> class BE {
T *data;
BE *l, *r;
public:
...
template<class U> friend class BT;
};
template<class T> class BT {
BE<T> *root;
public:
...
private:
...
};
This appears to work; however I have questions about what's going on underneath.
I originally tried to declare the friend as
template<class T> friend class BT;
however it appears necessary to use U (or something other than T) here, why is this? Does it imply that any particular BT is friend to any particular BE class?
The IBM page on templates and friends has examples of different type of friend relationships for functions but not classes (and guessing a syntax hasn't converged on the solution yet). I would prefer to understand how to get the specifications correct for the type of friend relationship I wish to define.
template<class T> class BE{
template<class T> friend class BT;
};
Is not allowed because template parameters cannot shadow each other. Nested templates must have different template parameter names.
template<typename T>
struct foo {
template<typename U>
friend class bar;
};
This means that bar is a friend of foo regardless of bar's template arguments. bar<char>, bar<int>, bar<float>, and any other bar would be friends of foo<char>.
template<typename T>
struct foo {
friend class bar<T>;
};
This means that bar is a friend of foo when bar's template argument matches foo's. Only bar<char> would be a friend of foo<char>.
In your case, friend class bar<T>; should be sufficient.
In order to befriend another same-type struct:
#include <iostream>
template<typename T_>
struct Foo
{
// Without this next line source.value_ later would be inaccessible.
template<typename> friend struct Foo;
Foo(T_ value) : value_(value) {}
template <typename AltT>
void display(AltT &&source) const
{
std::cout << "My value is " << value_ << " and my friend's value is " << source.value_ << ".\n";
}
protected:
T_ value_;
};
int main()
{
Foo<int> foo1(5);
Foo<std::string> foo2("banana");
foo1.display(foo2);
return 0;
}
With the output as follows:
My value is 5 and my friend's value is banana.
In template<typename> friend struct Foo; you shouldn't write T after typename/class otherwise it will cause a template param shadowing error.
It's not necessary to name the parameters so you get fewer points of failure if refactoring:
template <typename _KeyT, typename _ValueT> class hash_map_iterator{
template <typename, typename, int> friend class hash_map;
...
The best way to make a template class a friend of a template class is the following:
#include <iostream>
using namespace std;
template<typename T>
class B;
template<typename T>
class A
{
friend class B<T>;
private:
int height;
public:
A()//constructor
A(T val) //overloaded constructor
};
template<typename T>
class B
{
private:
...
public:
B()//constructor
B(T val) //overloaded constructor
};
In my case this solution works correctly:
template <typename T>
class DerivedClass1 : public BaseClass1 {
template<class T> friend class DerivedClass2;
private:
int a;
};
template <typename T>
class DerivedClass2 : public BaseClass1 {
void method() { this->i;}
};
I hope it will be helpful.

friend function using template classes c++

I made a class which has a friend function and when I declare it there are no problems but, when I write its code it returns me the error:
"Out-of-line definition of 'change' does not match any declaration in 'MyClass '".
Here's the code
template <class T>
class MyClass {
private:
T a;
public:
MyClass(T);
~MyClass();
friend void change(MyClass);
};
template <class T>
MyClass <T> :: MyClass(T value) {
a = value;
}
template <class T>
MyClass <T> :: ~MyClass() {}
template <class T>
void MyClass <T> :: change(MyClass class) { //Out-of-line definition of 'change' does not match any declaration in 'MyClass <T>'
a = class.a;
}
friend void change(MyClass); does not declare a member function of MyClass, it is an instruction for the compiler to grant the free function¹ void change(MyClass); access to private/protected members of MyClass.
The free function you grant access to MyClass would then have to look that way:
template <class S>
void change(MyClass<S> obj) {
obj.a; // obj.a can be accessed by the free function
}
But the friend then has to be declared that way in the class:
template <class T>
class MyClass {
private:
T a;
public:
MyClass(T);
~MyClass();
template <class S>
friend void change(MyClass<S>);
};
But based on a = class.a in change I think you actually want to have this:
template <class T>
class MyClass {
private:
T a;
public:
MyClass(T);
~MyClass();
void change(MyClass);
};
template <class T>
MyClass <T> :: MyClass(T value) {
a = value;
}
template <class T>
MyClass <T> :: ~MyClass() {}
template <class T>
void MyClass <T>::change(MyClass class) {
a = class.a;
}
A member function of MyClass can always access all members of any instance of MyClass.
1: What is the meaning of the term “free function” in C++?

Make all derived template classes friend of other class in C++

Let's say I have to following hierarchy:
template<class T> class Base {
protected:
T container;
};
template<class T> class Derived1 : public Base<T> {
public:
void f1() {
/* Does stuff with Base<T>::container */
}
};
template<class T> class Derived2 : public Base<T> {
public:
void f2() {
/* Does stuff with Base<T>::container */
}
};
Now I want an independent Class (not derived from Base) that can access the Base<T>::container directly from Base or any Derived class. I read about template friend classes and it seems to be the solution to my problem but I couldn't figure out the syntax yet.
I am looking for something like:
template<class T> class Foo{
template<T> friend class Base<T>; // <-- this does not work
public:
size_t bar(const Base<T> &b) const{
return b.container.size();
}
};
Derived1<std::vector<int> > d;
d.f1();
Foo<std::vector<int> > foo;
size_t s = foo.bar()
The friend class line causes an error: specialization of ‘template<class T> class Base’ must appear at namespace scope template<T> friend class Base<T> and the member variable container is still not accessible.
A couple of issues:
Just as you don't put a <T> after the class name when defining a class template:
template <class T> class X<T> { ... }; // WRONG
template <class T> class X { ... }; // RIGHT
you shouldn't put it after the class name when declaring a class template, whether in a forward declaration or friend declaration:
template <class T> class X<T>; // WRONG
template <class T> class X; // RIGHT - declares the template exists
template <class T> friend class X<T>; // WRONG
template <class T> friend class X; // RIGHT - says all specializations of X are friends
(Unless you're creating a class template partial specialization. For example, if class template X is already declared, then template <class T> class X<T*> { ... }; defines a partial specialization that will be used instead of the primary template when the template argument is a pointer.)
And you have the friend declaration backwards: it needs to appear inside the class with the non-public member(s), and name the other class(es) which are allowed to use the members. (If it worked the other way around, then any new class could gain access to any other class's private and protected members, without the permission of the owning class!)
So you would need:
template <class T> class Foo;
template<class T> class Base {
template <class U> friend class Foo;
protected:
T container;
};
The forward declaration of Foo is sometimes not needed, but I think it makes things clearer, and it can avoid gotchas when things start getting more complicated with namespaces, nested classes, etc.
Only Base can say Foo is its friend.
template<typename T> friend class Foo; // every Foo<T> is a friend of Base

Member function of nested class returns type of nested class

I have a struct within a class like this
template <class T>
class a {
struct b {
int var;
b *foo(const T&);
};
int var;
};
and I want to define foo outside of struct b.
How do I do that?
template <class T>
typename a<T>::b* a<T>::b::foo(const T&)
{
//code
}

Class template with template class friend, what's really going on here?

Let's say I'm creating a class for a binary tree, BT, and I have a class which describes an element of the tree, BE, something like
template<class T> class BE {
T *data;
BE *l, *r;
public:
...
template<class U> friend class BT;
};
template<class T> class BT {
BE<T> *root;
public:
...
private:
...
};
This appears to work; however I have questions about what's going on underneath.
I originally tried to declare the friend as
template<class T> friend class BT;
however it appears necessary to use U (or something other than T) here, why is this? Does it imply that any particular BT is friend to any particular BE class?
The IBM page on templates and friends has examples of different type of friend relationships for functions but not classes (and guessing a syntax hasn't converged on the solution yet). I would prefer to understand how to get the specifications correct for the type of friend relationship I wish to define.
template<class T> class BE{
template<class T> friend class BT;
};
Is not allowed because template parameters cannot shadow each other. Nested templates must have different template parameter names.
template<typename T>
struct foo {
template<typename U>
friend class bar;
};
This means that bar is a friend of foo regardless of bar's template arguments. bar<char>, bar<int>, bar<float>, and any other bar would be friends of foo<char>.
template<typename T>
struct foo {
friend class bar<T>;
};
This means that bar is a friend of foo when bar's template argument matches foo's. Only bar<char> would be a friend of foo<char>.
In your case, friend class bar<T>; should be sufficient.
In order to befriend another same-type struct:
#include <iostream>
template<typename T_>
struct Foo
{
// Without this next line source.value_ later would be inaccessible.
template<typename> friend struct Foo;
Foo(T_ value) : value_(value) {}
template <typename AltT>
void display(AltT &&source) const
{
std::cout << "My value is " << value_ << " and my friend's value is " << source.value_ << ".\n";
}
protected:
T_ value_;
};
int main()
{
Foo<int> foo1(5);
Foo<std::string> foo2("banana");
foo1.display(foo2);
return 0;
}
With the output as follows:
My value is 5 and my friend's value is banana.
In template<typename> friend struct Foo; you shouldn't write T after typename/class otherwise it will cause a template param shadowing error.
It's not necessary to name the parameters so you get fewer points of failure if refactoring:
template <typename _KeyT, typename _ValueT> class hash_map_iterator{
template <typename, typename, int> friend class hash_map;
...
The best way to make a template class a friend of a template class is the following:
#include <iostream>
using namespace std;
template<typename T>
class B;
template<typename T>
class A
{
friend class B<T>;
private:
int height;
public:
A()//constructor
A(T val) //overloaded constructor
};
template<typename T>
class B
{
private:
...
public:
B()//constructor
B(T val) //overloaded constructor
};
In my case this solution works correctly:
template <typename T>
class DerivedClass1 : public BaseClass1 {
template<class T> friend class DerivedClass2;
private:
int a;
};
template <typename T>
class DerivedClass2 : public BaseClass1 {
void method() { this->i;}
};
I hope it will be helpful.