So I have a class inside a foo namespace, which includes a friend function. Now I want the definition of the friend function to be in a different namespace bar so it can be called the way you see below. The error I get is that the private member val cannot be accessed.
Question: Why?
#include <iostream>
namespace foo
{
template<typename T>
class myclass
{
private:
T val;
public:
myclass(T v) : val(v) {}
template<class U>
friend void myfun(myclass<U>);
};
namespace bar
{
template<class U>
void myfun(myclass<U> a)
{
std::cout << a.val;
}
} //bar
} //foo
int main()
{
foo::myclass<int> a(5);
foo::bar::myfun(a);
}
You should declare foo::bar::myfun before the friend declaration and use appropriate namespace qualification (bar::):
namespace foo
{
template<typename T>
class myclass;
namespace bar
{
template<class U>
void myfun(myclass<U> a);
} //bar
template<typename T>
class myclass
{
private:
T val;
public:
myclass(T v) : val(v) {}
template<class U>
friend void bar::myfun(myclass<U>);
};
} //foo
Otherwise another function called myfun will be declared in the foo namespace by the friend declaration.
Related
I have the following template class and template function which intends to access the class' private data member:
#include <iostream>
template<class T>
class MyVar
{
int x;
};
template<class T>
void printVar(const MyVar<T>& var)
{
std::cout << var.x << std::endl;
}
template<class T>
void scanVar(MyVar<T>& var)
{
std::cin >> var.x;
}
struct Foo {};
int main(void)
{
MyVar<Foo> a;
scanVar(a);
printVar(a);
return 0;
}
To declare the two functions as MyVar<T>'s friend functions, I've tried the following ways inside the declaration of template<class T> class MyVar to declare friendship. None of them works. How should I do?
template<class T> friend void printVar(const MyVar&);
template<class T> friend void scanVar(MyVar&);
// compilation error
template<class T> friend void printVar(const MyVar<T>&);
template<class T> friend void scanVar(MyVar<T>&);
// compilation error
friend void printVar(const MyVar<T>&);
friend void scanVar(MyVar<T>&);
// link error
friend void printVar(const MyVar&);
friend void scanVar(MyVar&);
// link error too
The simplest option is to define the friend within the class:
template<class T>
class MyVar
{
int x;
friend void printVar(const MyVar & var) {
std::cout << var.x << std::endl;
}
friend void scanVar(MyVar & var) {
std::cin >> var.x;
}
};
The downside is that the functions can only be called through argument-dependent lookup. That's not a problem in your example, but might be a problem if they don't have a suitable argument, or you want to specify the name without calling it.
If you want a separate definition, then the template will have to be declared before the class definition (so it's available for a friend declaration), but defined afterwards (so it can access the class members). The class will also have to be declared before the function. This is a bit messy, so I'll only show one of the two functions:
template <typename T> class MyVar;
template <typename T> void printVar(const MyVar<T> & var);
template<class T>
class MyVar
{
int x;
friend void printVar<T>(const MyVar<T> & var);
};
template <typename T> void printVar(const MyVar<T> & var) {
std::cout << var.x << std::endl;
}
I managed to get the following work
#include <iostream>
template<class T>
class MyVar;
template<class T>
void printVar(const MyVar<T>& var);
template<class T>
void scanVar(MyVar<T>& var);
template<class T>
class MyVar
{
int x;
friend void printVar<T>(const MyVar<T>& var);
friend void scanVar<T>(MyVar<T>& var);
};
template<class T>
void printVar(const MyVar<T>& var)
{
std::cout << var.x << std::endl;
}
template<class T>
void scanVar(MyVar<T>& var)
{
std::cin >> var.x;
}
struct Foo {};
int main(void)
{
MyVar<Foo> a;
scanVar(a);
printVar(a);
return 0;
}
UPD: http://en.cppreference.com/w/cpp/language/friend talks about a similar case with operators under "Template friend operators":
A common use case for template friends is declaration of a non-member
operator overload that acts on a class template, e.g.
operator<<(std::ostream&, const Foo<T>&) for some user-defined
Foo<T>
Such operator can be defined in the class body, which has the effect
of generating a separate non-template operator<< for each T and
makes that non-template operator<< a friend of its Foo<T>
...
or the function template has to be declared as a template before the
class body, in which case the friend declaration within Foo<T> can
refer to the full specialization of operator<< for its T
This one compiles on MSVC2013. Basicly adds the forward declarations to class and functions before the friend
template<class T> class MyVar ; // class forward declaration
template<class T> ; // function forward declarations
void printVar(const MyVar<T>& var);
template<class T>
void scanVar(MyVar<T>& var);
template<class T>
class MyVar
{
friend void printVar<T>(const MyVar<T>&);
friend void scanVar<T>(MyVar<T>&);
int x;
};
template<class T>
void printVar(const MyVar<T>& var)
{
std::cout << var.x << std::endl;
}
template<class T>
void scanVar(MyVar<T>& var)
{
std::cin >> var.x;
}
struct Foo {};
int main1(void)
{
MyVar<Foo> a;
scanVar(a);
printVar(a);
return 0;
}
Well there is a solution that is both simple and involving separation between declaration & definition of the friend function. In the declaration of the friend function (inside the class) you have to give a different template param from the one the class accepts (and it make sense cause this function is not a member of this class).
template<class T>
class MyVar
{
int x;
template<typename Type>
friend void printVar(const MyVar<Type> & var);
template<typename Type>
friend void scanVar(MyVar<Type> & var);
};
template<typename T>
void printVar(const MyVar<T> & var) {
}
template<typename T>
void scanVar(MyVar<T> & var) {
}
No forward declaration needed, as well as there is a separation of declaration & definition.
I was learning about non-template friend function & template friend function to a templated class. So I tried the code below :
#include <iostream>
template<typename T>
class cl
{
private :
T val;
public:
cl()= default;
explicit cl(T v) : val(std::move(v)) {}
friend void non_template_friend(cl m);
};
template <typename T>
void non_template_friend(cl<T> m) { std::cout << m.val << std::endl;}
int main()
{
cl<int> c(10);
non_template_friend(c);
return 0;
}
so when I compile I got : undefined reference tonon_template_friend(cl)' ` So to resolve that I have to move the friend function definition inside the class definition like so :
template<typename T>
class cl
{
private :
T val;
public:
cl()= default;
explicit cl(T v) : val(std::move(v)) {}
friend void non_template_friend(cl m) { std::cout << m.val << std::endl;}
};
But I was wondering,is there any trick to do to be able to define the friend fuinction outside the class definition ?
Thank you.
If you want the definition outside the class, it needs to be a template function since it must be able to accept any kind of c1.
You can achieve this by forward declaring both the class and the function.
#include <iostream>
template<typename T>
class cl;
template<typename T>
void non_template_friend(cl<T> m);
template<typename T>
class cl
{
private :
T val;
public:
cl()= default;
explicit cl(T v) : val(std::move(v)) {}
friend void non_template_friend<T>(cl m); //Now we can refer to a specific instatiation of the template here
};
template <typename T>
void non_template_friend(cl<T> m) { std::cout << m.val << std::endl;}
int main()
{
cl<int> c(10);
non_template_friend(c);
return 0;
}
In the first program
template<typename T>
class cl
{
private :
T val;
public:
cl()= default;
explicit cl(T v) : val(std::move(v)) {}
friend void non_template_friend(cl m);
};
template <typename T>
void non_template_friend(cl<T> m) { std::cout << m.val << std::endl;}
You declared a non-template friend funcrion but then you declared and defined a template function with the same name/
A non-template friend function declaration means thatf you have to provide a set of overloaded non-template functions for specializations of the template class/
Here is a demonstrative program.
#include <iostream>
template<typename T>
class cl
{
private :
T val;
public:
cl()= default;
explicit cl(T v) : val(std::move(v)) {}
friend void non_template_friend(cl m) ;
};
void non_template_friend( cl<int> m) { std::cout << m.val << std::endl;}
void non_template_friend( cl<double> m) { std::cout << m.val << std::endl;}
int main()
{
cl<int> c(10);
non_template_friend(c);
cl<double> c2( 20.2 );
non_template_friend(c2);
return 0;
}
The program output is
10
20.2
That is in a template class a non-template friend function declaration is in fact declares a set of overloaded non-template functions.
How to conveniently declare many template functions as friend function of a template class?
Example:
template <typename T>
void funct1(MyClass<T> & A); //1.forward declaration.
template <typename T>
class MyClass{
protected:
T a;
friend funct1(MyClass<T> & A); //2.declare friend
}
template <typename T>
void funct1(MyClass<T> & A){ //3.actual implementation
++A.a;
}
step 1,2,3 get repeated for each of the many functions....
Is it possible to group all these function into something, then declare everything in that something are friends of the template class?
How about A friend class, all the functions can go into that one friend class:
#include <iostream>
using namespace std;
template <typename T>
class MyFriend;
template <typename T>
class MyClass{
protected:
T a;
public:
MyClass(T _a):a(_a) {}
friend MyFriend<T>;
};
template <typename T>
class MyFriend {
public:
void funct1(MyClass<T> &A) {
++A.a;
cout << "A.a: " << A.a << endl;
}
void funct2(MyClass<T> &B) {
B.a += 2;
cout << "A.a: " << B.a << endl;
}
};
int main() {
MyClass<int> myclass(0);
MyFriend<int> myfriend;
myfriend.funct1(myclass);
myfriend.funct2(myclass);
return 0;
}
Yes! You can make them static member functions of a class, and make that class a friend.
template <typename T>
class MyClass{
protected:
T a;
friend class MyFunctions;
}
In function myfun is there a way to access rhs.var without writing a public function which returns var? Also, as I understand, this happens because rhs could be a different type... Is this correct?
#include <iostream>
template<class T>
class foo
{
private:
T var;
public:
foo(T v) : var(v) {}
template<class Type>
void myfun(foo<Type>& rhs)
{
auto i = rhs.var; //BOOM
}
};
int main()
{
foo<int> a = 5;
foo<double> b = 2.2;
a.myfun(b);
}
Suggested Solutions
You could either provide a public accessor to your private member variable:
template<class T>
class foo {
T var;
public:
foo(T v) : var(v) {}
T getVar() const { return var; }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
template<class Type>
void myfun(foo<Type>& rhs) {
auto i = rhs.getVar();
^^^^^^^^
}
};
Or as already Dieter mentioned in the comments you could make your template class a friend:
template<class T>
class foo {
T var;
template <class> friend class foo;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
public:
foo(T v) : var(v) {}
template<class Type>
void myfun(foo<Type>& rhs) {
auto i = rhs.var;
}
};
Overview
The reason why the template member function myfun is not granted access to private member variable var of class template foo is that the compiler interprets class foo<Type> and class foo<T> as completely different class types, even though they would originate from the same template class definition. Thus, as being different class types the one cannot access the private members of the other.
you can define the second type as fried like:
template<class T>
class foo
{
private:
T var;
public:
foo(T v) : var(v) {}
template<class Type>
void myfun(foo<Type>& rhs)
{
auto i = rhs.var; //BOOM
}
template<class Type>
friend class foo;
};
live example
I have the following template class and template function which intends to access the class' private data member:
#include <iostream>
template<class T>
class MyVar
{
int x;
};
template<class T>
void printVar(const MyVar<T>& var)
{
std::cout << var.x << std::endl;
}
template<class T>
void scanVar(MyVar<T>& var)
{
std::cin >> var.x;
}
struct Foo {};
int main(void)
{
MyVar<Foo> a;
scanVar(a);
printVar(a);
return 0;
}
To declare the two functions as MyVar<T>'s friend functions, I've tried the following ways inside the declaration of template<class T> class MyVar to declare friendship. None of them works. How should I do?
template<class T> friend void printVar(const MyVar&);
template<class T> friend void scanVar(MyVar&);
// compilation error
template<class T> friend void printVar(const MyVar<T>&);
template<class T> friend void scanVar(MyVar<T>&);
// compilation error
friend void printVar(const MyVar<T>&);
friend void scanVar(MyVar<T>&);
// link error
friend void printVar(const MyVar&);
friend void scanVar(MyVar&);
// link error too
The simplest option is to define the friend within the class:
template<class T>
class MyVar
{
int x;
friend void printVar(const MyVar & var) {
std::cout << var.x << std::endl;
}
friend void scanVar(MyVar & var) {
std::cin >> var.x;
}
};
The downside is that the functions can only be called through argument-dependent lookup. That's not a problem in your example, but might be a problem if they don't have a suitable argument, or you want to specify the name without calling it.
If you want a separate definition, then the template will have to be declared before the class definition (so it's available for a friend declaration), but defined afterwards (so it can access the class members). The class will also have to be declared before the function. This is a bit messy, so I'll only show one of the two functions:
template <typename T> class MyVar;
template <typename T> void printVar(const MyVar<T> & var);
template<class T>
class MyVar
{
int x;
friend void printVar<T>(const MyVar<T> & var);
};
template <typename T> void printVar(const MyVar<T> & var) {
std::cout << var.x << std::endl;
}
I managed to get the following work
#include <iostream>
template<class T>
class MyVar;
template<class T>
void printVar(const MyVar<T>& var);
template<class T>
void scanVar(MyVar<T>& var);
template<class T>
class MyVar
{
int x;
friend void printVar<T>(const MyVar<T>& var);
friend void scanVar<T>(MyVar<T>& var);
};
template<class T>
void printVar(const MyVar<T>& var)
{
std::cout << var.x << std::endl;
}
template<class T>
void scanVar(MyVar<T>& var)
{
std::cin >> var.x;
}
struct Foo {};
int main(void)
{
MyVar<Foo> a;
scanVar(a);
printVar(a);
return 0;
}
UPD: http://en.cppreference.com/w/cpp/language/friend talks about a similar case with operators under "Template friend operators":
A common use case for template friends is declaration of a non-member
operator overload that acts on a class template, e.g.
operator<<(std::ostream&, const Foo<T>&) for some user-defined
Foo<T>
Such operator can be defined in the class body, which has the effect
of generating a separate non-template operator<< for each T and
makes that non-template operator<< a friend of its Foo<T>
...
or the function template has to be declared as a template before the
class body, in which case the friend declaration within Foo<T> can
refer to the full specialization of operator<< for its T
This one compiles on MSVC2013. Basicly adds the forward declarations to class and functions before the friend
template<class T> class MyVar ; // class forward declaration
template<class T> ; // function forward declarations
void printVar(const MyVar<T>& var);
template<class T>
void scanVar(MyVar<T>& var);
template<class T>
class MyVar
{
friend void printVar<T>(const MyVar<T>&);
friend void scanVar<T>(MyVar<T>&);
int x;
};
template<class T>
void printVar(const MyVar<T>& var)
{
std::cout << var.x << std::endl;
}
template<class T>
void scanVar(MyVar<T>& var)
{
std::cin >> var.x;
}
struct Foo {};
int main1(void)
{
MyVar<Foo> a;
scanVar(a);
printVar(a);
return 0;
}
Well there is a solution that is both simple and involving separation between declaration & definition of the friend function. In the declaration of the friend function (inside the class) you have to give a different template param from the one the class accepts (and it make sense cause this function is not a member of this class).
template<class T>
class MyVar
{
int x;
template<typename Type>
friend void printVar(const MyVar<Type> & var);
template<typename Type>
friend void scanVar(MyVar<Type> & var);
};
template<typename T>
void printVar(const MyVar<T> & var) {
}
template<typename T>
void scanVar(MyVar<T> & var) {
}
No forward declaration needed, as well as there is a separation of declaration & definition.