Class Template with Template Class Friend, What's Really Going on Here

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


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.

Templated friend class in nontemplate class, where friend also uses the class

The correct declaration of a template friend class is :

template<class F> friend class library_file;

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

Dependency in template friend of template class

[Edit:
The following works with both g++ 4.9.0 and clang 3.5 on my machine:

template<class T>
struct dummy {};

template<class T>
struct A {
private:
template<class U>
struct AConstructor {
static void construct(A<T>* thisPtr) {
thisPtr->foo = 42;
}
};

template<class>
friend class AConstructor;

public:
template<class U>
A(dummy<U>) {
AConstructor<U>::construct(this);
}

void print() const {
std::cout << foo << std::endl;
}

private:
int foo;
};

int main() {
A<void> foobar( (impl::dummy<void>()) );
foobar.print();
return 0;
}

]

For me, this:

template<class T> 
struct A; //forward declaration

namespace impl {

template<class T>
struct wrap {
template<class U>
struct AConstructor {
static void construct(A<T>* thisPtr) {
thisPtr->foo = 42;
}
};
//some partial specialization...
};

template<class T>
struct dummy{};

} //end of namespace

template<class T>
struct A {
template<class>
friend class impl::wrap<T>::AConstructor;

template<class U>
A(impl::dummy<U>) {
impl::template wrap<T>::template AConstructor<U>::construct(this);
}

void print() const {
std::cout << foo << std::endl;
}

private:
int foo;
};

int main() {
A<void> foobar( (impl::dummy<void>()) );
foobar.print();
return 0;
}

compiles with g++ 4.9.0 and work as expected (it displays 42 on stdout) although the compilation fails with clang 3.5, i'd like to say that it is a clang bug, but i must admit i am not really sure of that.
Still, you could find that useful if that was the case:

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

Template friend

However, i don't really like that design, are you sure you really need partial specialization of the constructors? You can't discard them with SFINAE, or access some subtypes with a trait class (or any other thing you want partial specialization for which can be replaced by something else)?

For instance one of these constructions:

#include <list>
#include <vector>

template<class T>
struct is_vector : std::false_type {};

template<class T>
struct is_vector<std::vector<T>> : std::true_type {};

struct A {
template<
class T, typename std::enable_if<is_vector<T>::value, void*>::type = nullptr
>
A(T) {
std::cout << "construction with a vector" << std::endl;
}

template<class T>
A(std::list<T>) {
std::cout << "construction with a list of " << typeid(T).name();
std::cout << std::endl;
}

template<
class T,
typename std::enable_if<!is_vector<T>::value, void**>::type = nullptr
>
A(T) {
std::cout << "construction with an iterator (supposedly) whose value_type "
"is";
std::cout << typeid(typename std::iterator_traits<T>::value_type).name();
std::cout << std::endl;
}
};

int main() {
A(std::vector<int>());
A(std::list<std::vector<int>>());
A((char*) nullptr);
return 0;
}

which displays this on my machine:

construction with a vector

construction with a list of NSt3__16vectorIiNS_9allocatorIiEEEE

construction with an iterator (supposedly) whose value_type isc

(of course i don't know exactly what you want to do, so i'm not sure, i'd have commented about this rather than put it in an answer, but i don't have enough reputation to do so, account created today)

Friend with own class template with other template parameter


template<class T, class... Ts>
class A {
template<class U, class... Us> friend class A; //here you go
};

There is no need to specify template arguments after A

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

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.

Some problems about class template's friend

Problem 1:

Do you really want to do it? Do you want A<int> to access B<float>? Usually you don't, but if you really want:

template <typename U>
friend class A;

Problem 2:

The problem in 2 is that you are not making the instantiation of the f1 template a friend, but rather you are trying to make a non-templated free function f1 that takes a B<int> your friend. The correct syntax to befriend a particular instantiation is cumbersome:

template <typename T> class B;
template <typename T> void f( B<T>& );
template <typename T>
class B {
friend void f<T>( B<T>& );
};

Problem 3:

To make all specializations of f1 a friend (again, do you really want this?), you can do the same approach as for the class template:

template <typename U>
friend void f1( B<U>& );

More on all those here

Class templates and friend Classes

If you lookup the syntax for template friends, you'll find the right way to do it:

class A {
template<typename T>
friend class B; // every B<T> is a friend of A

template<typename T>
friend void f(T) {} // every f<T> is a friend of A
};

Although you probably just want to friend the specific one:

friend class BinaryTree<T>;

Template class friendship

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.



Related Topics



Leave a reply



Submit