Trying to understand the "template <class U> friend class B;" syntax - c++

The following is a simple c++ program that compiles with my MinGW compiler, and executes as expected:
#include <iostream>
template <class T> class A {
T a;
template <class U> friend class B;
public:
A<T> (T t) : a(t) {}
};
template <class T> class B {
A<T> aa;
public:
B<T> (T t) : aa(t) {}
T getT() const {return aa.a;}
};
int main() {
B<int> b(5);
std::cout << "> " << b.getT() << std::endl;
}
Since B<T>::getT() accesses the private A<T>::a member, A<T> makes B<T> a friend with template <class U> friend class B; line.
Unfortunately, I don't know why this line needs to be written like this. Intuitively, I would have expected something like friend class B<T>, yet, this doesn't compile.
The meaning of the newly introduced U is unclear as well, since A's and B's dependant type is T in both cases.
So, in short, I'd appreciate any light on how the syntax for this line is derived or deduced.

There are many different permutations of friendship and templates.
Your present code makes any template specialization of B into a friend for A<T>, so for example B<char> is a friend of A<int>.
If you only wanted to make the matching A<T> a friend, you would say it like this:
template <typename> class B; // forward declare above!
template <typename T>
class A
{
// ...
friend class B<T>;
};

IMHO, friend class B<T>; would have worked had you inserted a forward declaration
template<class T> class B;
before that of class A<T>.
The template <class U> friend class B; makes every class B<U> a friend, not just class B<T>.

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.

What must be done for a static template function defined in a nested class to be declared a friend in a sibling nested class?

Using GCC 4.8.2 on Linux, I want to grant the factory method Create() access to the private constructor of class C, but I get "error: 'Create' was not declared in this scope" when attempting to declare a specialized friend. How do I get this to work without opening up the declaration to all types for B::Create()?
template <typename T> class A {
public:
class B;
template <typename U> class C;
};
template <typename T>
class A<T>::B {
public:
template <typename U> static void Create();
};
template <typename T> template <typename U>
class A<T>::C {
C() = default;
friend void B::Create<U>();
};
template <typename T> template <typename U>
void A<T>::B::Create() {
C<U>{};
}
int main() {
A<int>::B::Create<char>();
}
I think you have run into a compiler defect. The following code, that uses only one layer of templates, works fine in g++ 4.8.2.
class Foo
{
public:
template <typename U> static Foo* Create();
};
template <typename U> class Bar : public Foo
{
private:
Bar() = default;
friend Foo* Foo::Create<U>();
};
template <typename U>
Foo* Foo::Create() {
return new Bar<U>();
}
However, the same compiler fails to compile your code. One work around, which I think you have already tried, is to replace
friend B* B::Create<U>();
with
template <typename V>
friend B* B::Create<V>();
I just tested your code in MSVC++ and it was failing there too. I was able to fix it by just giving the friend declaration a more explicit name. Remember, you can provide fully qualified names anywhere!
I just replaced
friend B* B::Create<U>();
with
friend B* A<T>::B::Create<U>();
I'll fire up MinGW and see if it actually does what you expect it to do.

How to use friend keyword for template class

lets say that I have 2 template classes, A and B. If I want to make B a friend of A, what would I say ?
class<template T>
class A
{
public:
friend class B<T>; // ???
};
class<template T>
class B
{
};
To use a symbol, it must be declared or defined, this is the same in template. You need to forward declare template B. Also your syntax(class<template T>) to declare template class is not valid, it should be template <class T>.
This should work:
template <typename T> // typename can be replaced with class
class B;
template <typename T>
class A
{
public:
friend class B<T>;
};
template <typename T>
class B
{
};

friend function of a templated class needs access to member type

I need to define a friend function for the templated class. The function has
return type that is a member type of the class. Now, I can not declare it beforehand, since the the return type is not known at the time. Something like this
template<class T> class A;
//This doesn't work: error: need ‘typename’ before...
template<class T> A<T>::member_type fcn(A<T>::member_type);
//This doesn't work: error: template declaration of ‘typename...
template<class T> typename A<T>::member_type fcn(A<T>::member_type);
template<class T>
class A{
public:
typedef int member_type;
friend member_type fcn<T>(member_type);
};
How do I do this?
I managed to compile that code on g++ using :
template<class T> typename A<T>::member_type fcn(typename A<T>::member_type);
(Thus a second 'typename' was required)
You need to say typename also in the argument:
template <class T>
typename A<T>::member_type fcn(typename A<T>::member_type);
// ^^^^^^^^
Otherwise there's no problem with your code, as long as all the template definitions appear before the function template is first instantiated.
It seems that in your particular example nothing in fcn function actually depends on class A. It doesn't even need to access any of the A's methods/fields, neither public nor protected/private. So it doesn't make sense. It would have made some sense otherwise, but at any rate it seems like it is worth re-thinking your problem and come up with a cleaner solution that does not need a hack like that. If, after a deep thought, you still believe you need it, you can do something like this:
#include <cstdio>
template<typename T> typename T::member_type fcn(const T & v) {
return v.value_;
}
template<class T>
class A {
public:
typedef T member_type;
friend member_type fcn< A<T> >(const A<T> &);
A() : value_(1986) {}
private:
T value_;
};
int main()
{
A<int> a;
printf("The value is: %d\n", fcn(a));
}
Notable thing in the above example is that you need to de-couple a cross dependency and make your free-function not depend on a declaration of class A. If you still feel like you need that coupling, the following code works, too:
#include <cstdio>
template <typename T>
class A;
template <typename T> typename A<T>::member_type fcn(const A<T> & v) {
return v.value_;
}
template <typename T>
class A {
public:
typedef int member_type;
friend member_type fcn<T>(const A<T> &);
A() : value_(1986) {}
private:
member_type value_;
};
int main()
{
A<void> a;
printf("The value is: %d\n", fcn(a));
}
Hope it helps. Good Luck!
This may by now be redundant with someone else's answer, but here's a complete, testable solution. The final function definition is a template specialization of fcn, which will produce a compiler error indicating that A<double>::x is not accessible from fcn<int>, but A<int>::x is accessible.
template<class T> class A;
template <typename U>
typename A<U>::member_type fcn(typename A<U>::member_type);
template<class T>
class A {
int x;
public:
typedef int member_type;
friend typename A<T>::member_type fcn<T>(typename A<T>::member_type);
};
template<>
int fcn<int>(int x)
{
A<int> i;
A<double> d;
i.x = 0; // permitted
d.x = 0; // forbidden
return 0;
}

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.