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
How to Assert If a Std::Mutex Is Locked
Linux C++ Error: Undefined Reference to 'Dlopen'
The Simplest and Neatest C++11 Scopeguard
How to Monitor a Folder with All Subfolders and Files Inside
String Conversion with Boost Locale: Different Behaviour on Windows and Linux
Are There Any Way to Link My Program with Wine-Compiled Part
How to Create a Game Loop with Xlib
Why Can't I Add a Qgridlayout to a Qmainwindow
Why Isn't Malloc Filling Up Memory
Determine If Linux or Windows in C++
Get Computer Name and Logged User Name
How to Force Linker to Use Shared Library Instead of Static Library
How to Install the Openssl Libraries on Ubuntu
How to Create Minidump for My Process When It Crashes
What Are the Rules for the "..." Token in the Context of Variadic Templates