My question is related to this question.
#include<iostream>
template< typename T >
class T1 {
public:
T i;
void display()
{
std::cout<<i<<"\n"<<j<<"\n"<<k;
}
protected:
T j;
private:
T k;
friend void Test( T1 &obj);
};
template<typename T>
void Test(T1<T> &obj)
{
T a=T();
obj.i=a;
obj.j=a;
obj.k=a;
}
int main()
{
T1<int>a;
Test(a);
a.display();
}
Why doesn't the above code compile?
friend void Test( T1 &obj); declares a non template function.
Declare it as a template.
Try this :
....
private:
T k;
template<typename U>
friend void Test( T1<U> &obj);
};
Related
Here is the context.. I'm compiling with g++.
template<typename T>
class Array;
template<typename T>
int length(Array<T>& a);
template<typename T>
class Array
{
public:
//...
private:
T* a;
int b;
template<typename>
friend int length(Array<T>&);
};
template<typename T>
int length(Array<T>& a)
{
return a.b;
}
Is there a way to always declare "the corresponding friend length function" (i.e. length) if "the class is defined (i.e. Array)?
I thought maybe explicitely instantiate it like..
...
template<typename T>
class Array
{
public:
...
private:
...
template int length<T>(Array<T>&);
friend int length(Array<T>&);
};
...
NOTE: the above doesn't compile
Yes, you simply need to fix the declaration:
private:
T* a;
int b;
friend int length<>(Array<T>&);
It should be
template<typename T>
class Array
{
public:
//...
private:
T* a;
int b;
friend int length<>(Array&);
};
Demo
Your template<typename /*U*/> friend int length(Array<T>&); doesn't match outside template.
I think you can fix your code like this:
template<typename T>
class Array
{
public:
//...
int getB() { return b;};
private:
T* a;
int b;
template<typename>
friend int length(Array<T>&);
};
template<typename T>
int length(Array<T>& a)
{
return a.getB();
}
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.
I want to explicitly instantiate template member but without instantiation of the template class. But I am getting compiler errors, so is this possible ? Here is my code:
//mytemplate.h
template <class T>
class mytemplate
{
public:
mytemplate(T* tt)
{
mT = tt;
}
template<class B>
void print(const B& bb);
T* mT;
};
//in mytemplate.cpp
#include "mytemplate.h"
template<typename T>
template<typename B>
void mytemplate<T>:: print(const B& bb)
{
B b = bb;
}
template<typename T> void mytemplate<T>::print<float>(const float&) const;
template<typename T> void mytemplate<T>::print<int>(const int&) const;
// main.cpp
int main()
{
int d =0;
mytemplate<int> k(&d);
k.print<float>(4.0);
}
With templates, it always helps to decompose the problem into the smallest possible building block. mytemplate::print can be written in terms of a call to a template free function.
This way you can achieve the effect of partial specialisation of a member function.
A leading question here is "what should the print() method do?". Here is an example in which mytemplate<T> provides a printing policy to a free function. There is no reason of course that the policy could not be some other class which has been constructed via some other (possibly specialised) template free function.
// Policy is a concept which supports 2 methods:
// print_prefix() and print_postfix()
//
template<class Policy, class B>
void print_with_policy(const Policy& policy, const B& value) const
{
policy.print_prefix();
cout << value;
policy.print_postifx();
}
template<class T>
struct mytemplate
{
// implement in terms of a free function
template<class B> void print(const B& value) {
print_with_policy(*this, value);
}
// policy concept implementation
void print_prefix() const {
cout << "prefix-";
}
void print_postfix() const {
cout << "-postfix";
}
};
extending the example to use a separate policy class with a specialisation for strings:
template<typename B>
struct default_policy {
default_policy(const B& value) : _value(value) {}
void operator()() const {
cout << "(" << _value << ")";
}
private:
const B& _value;
};
template<typename B>
struct quoted_policy {
quoted_policy(const B& value) : _value(value) {}
void operator()() const {
cout << '"' << _value << '"';
}
private:
const B& _value;
};
template<class B>
default_policy<B> make_policy(const B& value) {
return default_policy<B>(value);
}
// overload for B being a string
quoted_policy<std::string> make_policy(const std::string& value) {
return quoted_policy<std::string>(value);
}
template<class T>
struct mytemplate
{
// implement in terms of a free function
template<class B> void print(const B& value) {
make_policy(value)();
cout << endl;
}
};
int main()
{
struct foo{};
mytemplate<foo> fooplate;
fooplate.print(int(8));
fooplate.print(std::string { "a string" });
fooplate.print("not a string");
return 0;
}
output:
(8)
"a string"
(not a string)
I have a problem with two derived classes. I need that one receive the other as argument, but my code doesn't work (I semplified it to be more clear).
class:
#include<iostream>
#include<stdexcept>
using namespace std;
template <typename T> class A;
template <typename T> class B;
template <typename T> class C;
template <typename T> class A{
protected:
T **m;
void allocate_mem(T ***ptr){
*ptr = new T*[1];
(*ptr)[0] = new T[1];
}
public:
A(){
throw logic_error("Error!");
}
~A(){
delete[] m[0];
delete[] m;
}
T say_elem(){
return m[0][0];
}
};
template <typename T> class B: public A<T>{
public:
B(int val){
A<T>::allocate_mem(& this->m);
A<T>::m[0][0] = val;
}
};
template <typename T> class C: public A<T>{
public:
C(double val){
A<T>::allocate_mem(& this->m);
A<T>::m[0][0] = 1;
}
void renew(const B<T> &b){
if(A<T>::b.say_elem() > 0){
A<T>::m[0][0] = 1000;
}
}
};
main:
#include<iostream>
#include "class.cpp"
using namespace std;
int main(int argc, char **argv){
B <int> bbb(4);
C <double> ccc(5);
ccc.renew(bbb);
//no matching function for call to 'C<double>::renew(B<int>&)'
return 0;
}
the error is indicated above, what i need to do?
You are trying to call C<T>::renew(const B<T> &) with the wrong argument. What renew is expecting (in the call to the instance C<double>) is const B<double>&, not const B<int>&. They are two completely different classes. If you want to allow a B class with a different template parameter, templatize the function:
template<class U>
void renew(const B<U> &b) {
if(b.say_elem() > 0){
m[0][0] = 1000;
}
}
Ok, I combined Jefffrey's correct answer with my note from the comments to give a complete compiling and running code (which will throw logic_error("Error!") by the way, but this is off-topic).
#include<iostream>
#include<stdexcept>
using namespace std;
template <typename T> class A;
template <typename T> class B;
template <typename T> class C;
template <typename T> class A{
protected:
T **m;
void allocate_mem(T ***ptr){
*ptr = new T*[1];
(*ptr)[0] = new T[1];
}
public:
A(){
throw logic_error("Error!"); // remove this line for expected behavior
}
~A(){
delete[] m[0];
delete[] m;
}
T say_elem() const {
return m[0][0];
}
};
template <typename T> class B: public A<T>{
public:
B(int val){
A<T>::allocate_mem(& this->m);
A<T>::m[0][0] = val;
}
};
template <typename T> class C: public A<T>{
public:
C(double val){
A<T>::allocate_mem(& this->m);
A<T>::m[0][0] = 1;
}
template <typename U>
void renew(const B<U> &b){
if(b.A<U>::say_elem() > 0){
A<T>::m[0][0] = 1000;
}
}
};
int main(int argc, char **argv){
B <int> bbb(4);
C <double> ccc(5);
ccc.renew(bbb);
return 0;
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to allow template function to have friend(-like) access?
How do I give function template Load friend access to class Foo?
The objective here is to restrict access to the constructor: only function template Load may construct.
CODE (please ignore memory leak)
class Foo {
Foo() { }
template<> friend Foo const& Load<Foo>(); // error here
};
template<typename T>
T const&
Load() { return *(new T); }
int main( int argc, char* argv[] )
{
Foo const& f = Load<Foo>();
}
This should work.
template<typename T> T const& Load() { return *(new T); }
class Foo {
Foo() { }
friend Foo const& Load<Foo>();
};
Doing it like this should work:
#include <iostream>
template <typename T>
const T&
load(void)
{
return *(new T);
}
class foo
{
private:
foo(void)
{
std::cout << "hello!" << std::endl;
}
template <typename T>
friend const T& load();
};
int
main(void)
{
const foo& f = load<foo>();
return 0;
}