Template Friending syntax - c++

Say I have two Template classes.
template<class T>
class baseclass1
{
template<class> friend class baseclass2;
}
template<class D>
class baseclass2
{
template<class T> void foo( D& x, T& y)
{
...
}
}
The Above code allows all types of baseclass1 to friend all types of baseclass2, a many-to-many relationship. I have two questions,
What is the syntax to allow baseclass1 to friend just the function
baseclass2<class D>::foo<class T>( D& x, T& y).
And, what is the syntax to allow baseclass1 to friend just the function
baseclass2<class D>::foo<class T>( D& x, T& y) where T from baseclass1 matches The T from Function foo.
EDIT
To those who keep claiming you can't friend a template specialization. This code works
template<class cake>
class foo
{
public:
static void bar(cake x)
{
cout << x.x;
}
};
class pie
{
public:
void set( int y){ x = y; }
private:
int x;
friend void foo<pie>::bar(pie x);
};
class muffin
{
public:
void set( int y){ x = y; }
private:
int x;
friend void foo<pie>::bar(pie x);
};
int main
{
pie x;
x.set(5);
foo<pie>::bar(x);
muffin y;
y.set(5);
//foo<muffin>::foo(y); //Causes a compilation Error because I only friended the pie specialization
}
Even notice where muffin friends the wrong foo, and still causes a compilation error. This works with both functions and classes. I am totally willing to accept that this isn't possible in my specific situation (It's actually looking more and more that way) I'd just like to understand why.

Befriending all possible specializations of baseclass2<D>::foo is rather easy:
template<class T> class baseclass1;
template<class D>
class baseclass2{
public:
template<class T>
void foo(D&, T&){ baseclass1<T> x; x.priv_foo(); }
};
template<class T>
class baseclass1{
template<class D>
template<class U>
friend void baseclass2<D>::foo(D&, U&);
void priv_foo(){}
};
template<class T>
class baseclass1{
template<class D>
template<class U>
friend void baseclass2<D>::foo(D&, U&);
};
Live example.
A forward declaration of baseclass2 (so baseclass1 knows that baseclass2 exists and is a template) and two templates, one for the class, one for the function. It also looks like this for out-of-class definitions for function templates of class templates. :)
Befriending specifically baseclass2<D>::foo<T> is not possible, however, or I can't find
the correct syntax for it.
A workaround might be some global function that forwards the access and together with the passkey pattern, but meh, it's a mess (imho):
template<class D> class baseclass2;
template<class D, class T>
void baseclass2_foo(baseclass2<D>& b, D&, T&);
template<class D, class T>
class baseclass2_foo_key{
baseclass2_foo_key(){} // private ctor
friend void baseclass2_foo<>(baseclass2<D>&, D&, T&);
};
template<class T>
class baseclass1{
public: // public access, but only baseclass2_foo can create the key
template<class D>
void priv_foo(baseclass2_foo_key<D, T> const&){}
};
template<class D, class T>
void baseclass2_foo(baseclass2<D>&, D&, T&){
baseclass1<T> x;
x.priv_foo(baseclass2_foo_key<D, T>());
}
template<class D>
class baseclass2{
public:
template<class T>
void foo(D& d, T& t){ baseclass2_foo(*this, d, t); }
};
Live example.

AFAIK you may specify all instantiation of foo as friend but not an specific instantiation:
template< class T >
class C1 {
public:
template< class Q > void foo( T& x, Q& y ) {
}
};
template< class T >
class C2 {
template< class Y >
template< class Q > friend void C1<Y>::foo( Y&, Q& );
};

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.

Template factory function with additional args: friendship issue

I'm working on a piece of code that looks like this:
template<typename T>
class A {
// makeA should become a friend
A() {}
};
template<typename T, typename U>
A<T> makeA(const U & u) {
(void) u;
return A<T>();
}
int main() {
makeA<double>(3);
return 0;
}
But I cannot let makeA become a friend of A. Is this possible? What is the right syntax?
You could make it friend as:
template<typename T>
class A
{
template<typename TT, typename U>
friend A<TT> makeA(const U & u) ;
};
You could even define the friend function inside the class.
While the solution
template <typename T>
class A
{
template<typename TT, typename U>
friend A<TT> makeA(const U & u) ;
};
works, it suffers from the side effect that makeA<int, int> is a friend of not only A<int> but also a friend of A<double>, A<char>, etc. In other workds, makeA<TT, U> is a friend of every A<T>. The friendship granted by A<T> is too broad.
You can limit that by using a different design.
template <typename T> class AMaker;
template <typename T>
class A
{
A() {}
friend class AMaker<T>;
};
template<typename T> class AMaker
{
public:
template <typename U>
static A<T> make(const U & u)
{
(void) u;
return A<T>();
}
};
int main()
{
A<double> x = AMaker<double>::make(3);
return 0;
}
Here, friendship granted by A<T> is limited to only AMaker<T>. AMaker<int> is friend of A<int> but not of A<double>.
I have done some changes in your program
template
class A {
// makeA should become a friend
A() {}
public:
template<typename S,typename U>
friend A<S> makeA(const U & u); //this is correct way to makeA friend of A
};
template<typename T, typename U>
A<T> makeA(const U & u) {
(void) u;
return A<T>();
}
int main() {
makeA<double>(3);
return 0;
}
Now it will work as you can see here
http://ideone.com/1F1l3o
Here is a solution that does not use friend:
template<class T>
class A {
A() {}
public:
template<class U> static A make(U && u) {
return A();
}
};
template<class T, class U>
A<T> makeA(U && u) {
return A<T>::template make<U>(std::forward<U>(u));
}

What does `template <class> friend class Foo` mean?

I'm exploring the boost::iterator_facade and came across this bit of code:
friend class boost::iterator_core_access;
template <class> friend class Iterator;
What does the second line mean? I'm familiar with friend classes, but I don't think I've seen template <class> in front of anything before.
Here's the context:
template <class Value>
class node_iter
: public boost::iterator_facade<
node_iter<Value>
, Value
, boost::forward_traversal_tag
>
{
public:
node_iter()
: m_node(0) {}
explicit node_iter(Value* p)
: m_node(p) {}
template <class OtherValue>
node_iter(node_iter<OtherValue> const& other)
: m_node(other.m_node) {}
private:
friend class boost::iterator_core_access;
template <class> friend class node_iter;
template <class OtherValue>
bool equal(node_iter<OtherValue> const& other) const
{
return this->m_node == other.m_node;
}
void increment()
{ m_node = m_node->next(); }
Value& dereference() const
{ return *m_node; }
Value* m_node;
};
typedef impl::node_iterator<node_base> node_iterator;
typedef impl::node_iterator<node_base const> node_const_iterator;
It just means Iterator is a template class with one template parameter. The friendship is granted to all instantiations of Iterator.
Iterator<int> is a friend of the class.
Iterator<bool> is a friend of the class.
...
Iterator<MyClass> is a friend of the class.
You get the idea.
Example Usage
Say you have a class template Foo.
template <typename T> class Foo
{
public:
Foo() : data(0) {}
prvavte:
T data;
};
When you instantiate the class template using:
Foo<int> a;
Foo<float> b;
you are creating two classes at compile time. Foo<int> does not have access to the private section of Foo<float> and vice versa. That is an inconvenience some times.
You can't do:
b = a; // If you wanted to pull the data from a and put it in b.
Even if you added an assignment operator to the class,
template <typename T> class Foo
{
public:
Foo() : data(0) {}
template <typename T2> Foo& operator=(Foo<T2> const& rhs)
{
this->data = rhs.data;
return *this;
}
private:
T data;
};
It won't work because Foo<T> doesn't have access to the private sections of Foo<T2>. To get around that you can use a friend declaration.
template <typename T> class Foo
{
public:
template <class> friend class Foo;
Foo() : data(0) {}
template <typename T2> Foo& operator=(Foo<T2> const& rhs)
{
this->data = rhs.data;
return *this;
}
private:
T data;
};
Now, you can use:
Foo<int> a;
Foo<float> b;
b = a;
Explicit Instantiation: http://www.cplusplus.com/articles/1C75fSEw/
It allows you to instantiate the template without actually using it.

How do you define a nested templated class' method outside of the class declaration?

How do I define func outside of the class declaration, below class A{...};?
template<typename T>
class A
{
template<typename Q>
class B
{
static void func(const A<T>& a){} // How do I define this function outside of the class declaration?
};
};
With a double template:
template<typename T>
template<typename Q>
void A<T>::B<Q>::func(const A<T>& a)
{
}
It's fairly straight-forward:
template<typename T>
template<typename Q>
void A<T>::B<Q>::func(const A<T>& a) { }
Basically it's the same technique as defining a templated class method outside the declaration of a class template. For instance:
template<typename T>
class test
{
template<typename U>
void func(const U& u);
};
You would define func outside the class like so:
template<typename T>
template<typename U>
void test<T>::func(const U& u) { }

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.