Here is my class declaration:
template <class T>
class Sptr {
template<typename U> friend class Sptr;
template <typename T1, typename T2>
friend bool operator==(const Sptr<T1> &a, const Sptr<T2> &b);
template <typename U>
friend Sptr<T> static_pointer_cast(const Sptr<U> &sp);
private:
RC* ref; //reference counter
T* obj;//pointer to current obj
std::function<void()> destroyData;
bool ok_;
public:
Sptr();
~Sptr();
template <typename U>
Sptr(U *);
Sptr(const Sptr &);
template <typename U>
Sptr(const Sptr<U> &);
template <typename U>
Sptr<T> &operator=(const Sptr<U> &);
Sptr<T> &operator=(const Sptr<T> &);
void reset();
T* operator->() const
{return obj;};
T& operator*() const
{return *obj;};
T* get() const
{return obj;};
explicit operator bool() const {
return ok_;
}
};
Below is the code thats complaining of access problem
template <typename T, typename U>
Sptr<T> static_pointer_cast(const Sptr<U> &sp) {
//do something
Sptr<U> answer;
answer.obj = sp.obj;
answer.ref = sp.ref;
answer.destroyData = sp.destroyData;
answer.ok_ = sp.ok_;
return answer;
}
when I compile with the following code:
Sptr<Derived> sp(new Derived);
Sptr<Base1> sp2(sp);
// Sptr<Derived> sp3(sp2); // Should give a syntax error.
Sptr<Derived> sp3(static_pointer_cast<Derived>(sp2));
// Sptr<Derived> sp4(dynamic_pointer_cast<Derived>(sp2)); // Should give syntax error about polymorphism.
I have already made it a friend function. Why is it not able to access the variables and how to correct it?
This is a bit tricky. Your code compiles if you replace
template <typename U>
friend Sptr<T> static_pointer_cast(const Sptr<U> &sp);
with
template <typename T1, typename T2>
friend Sptr<T1> static_pointer_cast(const Sptr<T2> &sp);
The reason is the following (I am not 100% sure, so please someone approve / dis-approve):
When Sptr<T> is instantiated, e.g. with T = Derived, the resulting class definition (Sptr<Derived>) defines a friend function having the following signature:
template <typename U>
friend Sptr<Derived> static_pointer_cast(const Sptr<U> &sp);
So this is a function which only has one template parameter. But the function you defined has two template parameters.
Your call to this templated function is a specialization which looks like this:
Sptr<Derived> static_pointer_cast(const Sptr<Base1> &sp) {
//do something
Sptr<Derived> answer;
answer.obj = sp.obj;
answer.ref = sp.ref;
answer.destroyData = sp.destroyData;
answer.ok_ = sp.ok_;
return answer;
}
So it tries to access both Base1 and Derived, but it's only a friend of Derived, not of Base1. This last sentence is the important thing, and changing it to a friend function with two template parameters solves this issue.
You said friend sptr<t>, which means it can only access the private members of sptrs to the same type. since sp2 is not a sptr( t is derived) it is not a friend. Try :
template< class u, class v> friend sptr<u> static_pointer_cast(const sptr<v> &sp);
Related
I have a template class alpha_x give as,
template <typename T,typename U>
struct alpha_x {
const T & alpha;
const Scalar<U> & x;
alpha_x(const T & a_, const Scalar<U> & x_) : alpha(a_), x(x_) {};
};
I have another class with an overload for operator =
template <typename T>
class Scalar{
...
template <typename U,typename V>
const Scalar<T> & operator = (alpha_x<U,V> c);
...
}
When we try to define this function,
template <typename T,typename U,typename V>
const Scalar<T> & Scalar<T>::operator = (alpha_x<U,V> c){
//do something...
}
Now this gives an error "Too many template parameters in template redeclaration". How do I sort this out?
T template parameter is a class Scalar's template parameter. Thus it needs to be specified in a separate template parameter list.
Following would work:
template <typename T>
template <typename U, typename V>
const Scalar<T> & Scalar<T>::operator = (alpha_x<U,V> c){
// do something...
}
Assume we have a template class with friend function:
template<class T>
class A {
friend A operator+ (int, const A&);
};
This function is implemented somewhere below:
template<class T>
A<T> operator+ (int i, const A<T>& a) {
...
}
And also there is force instantiation of class template further below:
template class A<int>;
Does this imply that operator+(int, A<int>) will be compiled? Or do I have to force instantiate it separately to achieve that?
Template parameters aren't automatically forwarded to friend declarations. You need to specify a template parameter for the function as well:
template<class T>
class A {
template<class U>
friend A<U> operator+ (int, const A<U>&);
};
Implementation is almost correct, should be
template<class T>
A<T> operator+ (int i, const A<T>& a) {
// ^^^
// ...
}
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));
}
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.
Hi I am trying to build empty functions for templates so that I can later fill in the details. Here is my code:
namespace my {
template <class T>
class Sptr {
private:
//some kind of pointer
//one to current obj
T obj;
size_t reference_count;
//one to original obj
public:
template <typename U> Sptr(U *);
Sptr(const Sptr &);
//template <typename U> Sptr(const Sptr<U> &);
~Sptr();
T* operator->() {return &obj;};
template <typename U> Sptr<T> &operator=(const Sptr<U> &);
//overload *,->,=,copy-constructor
// const-ness should be preserved.
// Test for null using safe-bool idiom
// Static casting, returns a smart pointer
};
template <typename U> Sptr<U>::Sptr(U* u) {
//do something
}
template <typename T> Sptr<T>::Sptr(const Sptr<T> ©Obj) {
//do copy constructor stuff
}
template <typename T> Sptr<T>::Sptr& operator=(const Sptr<T> &T) {
return *this;
}
}
But I get the following error when I compile it.
Sptr.hpp:30:24: error: prototype for ‘my::Sptr<T>::Sptr(U*)’ does not match any in class ‘my::Sptr<T>’
Sptr.hpp:17:3: error: candidates are: my::Sptr<T>::Sptr(const my::Sptr<T>&)
Sptr.hpp:16:25: error: template<class T> template<class U> my::Sptr::Sptr(U*)
Sptr.hpp:38:24: error: ‘my::Sptr<T>::Sptr’ names the constructor, not the type
How do I solve them?
template <typename U> Sptr<U>::Sptr(U* u) {
//do something
}
should be
template <typename T>
template <typename U>
Sptr<T>::Sptr(U* u) {
//do something
}
similarly for the other member function templates.
The way you define member functions of a class template is incorrect. Here is how you should define the constructor template:
template<typename T> // <== template parameter declaration for Sprt<T>
template<typename U> // <== template parameter declaration for constructor
Sptr<T>::Sptr(U* u) {
//do something
}
And here is how you should define the operator =:
template <typename T> // <== template parameter declaration for Sprt<T>
template<typename U> // <== template parameter declaration for operator
Sptr<T>& Sptr<T>::operator=(const Sptr<U> &t) {
return *this;
}
You define both the constructor and operator= as template functions. I'm not sure you actually want that. Shouldn't they just be taking T as arguments? Are you sure you don't want this for your constructor declaration:
Sptr(T*);
If you really do want them to be function templates, this is incorrect:
template <typename U> Sptr<U>::Sptr(U* u) {
//do something
}
When you have a function template inside a function class, you need to give both sets of template arguments:
template <typename T>
template <typename U>
Sptr<T>::Sptr(U* u) {
//do something
}