Can someone please clarify inner class use with templates? I have searched through books and internet examples to learn templates but few examples show inner class usage. What I gathered so far is
template <class T>
class A
{
class B
{
B()
~B()
}
A();
~A();
B* a(T i, B* l);
}
From reading this and this I believe I should define outer class constructor as
template <class T>
class A<T>::A()
{
}
but how am I defining the inner class constructor definition? How do I define the definition of a? I have struggled with this for most of the day trying to figure this out and really appreciate assistance.
You shouldn't use class in the definition of the constructor of A, it should be
template <class T>
A<T>::A()
{
}
And for the constructor of B,
template <class T>
A<T>::B::B()
{
}
And for the member function a, use typename when refers to A<T>::B
template <class T>
typename A<T>::B* A<T>::a(T i, typename A<T>::B* l)
{
return ...;
}
LIVE
Related
I need to define a friend function for the templated class. The function has
return type that is a member type of the class. Now, I can not declare it beforehand, since the the return type is not known at the time. Something like this
template<class T> class A;
//This doesn't work: error: need ‘typename’ before...
template<class T> A<T>::member_type fcn(A<T>::member_type);
//This doesn't work: error: template declaration of ‘typename...
template<class T> typename A<T>::member_type fcn(A<T>::member_type);
template<class T>
class A{
public:
typedef int member_type;
friend member_type fcn<T>(member_type);
};
How do I do this?
I managed to compile that code on g++ using :
template<class T> typename A<T>::member_type fcn(typename A<T>::member_type);
(Thus a second 'typename' was required)
You need to say typename also in the argument:
template <class T>
typename A<T>::member_type fcn(typename A<T>::member_type);
// ^^^^^^^^
Otherwise there's no problem with your code, as long as all the template definitions appear before the function template is first instantiated.
It seems that in your particular example nothing in fcn function actually depends on class A. It doesn't even need to access any of the A's methods/fields, neither public nor protected/private. So it doesn't make sense. It would have made some sense otherwise, but at any rate it seems like it is worth re-thinking your problem and come up with a cleaner solution that does not need a hack like that. If, after a deep thought, you still believe you need it, you can do something like this:
#include <cstdio>
template<typename T> typename T::member_type fcn(const T & v) {
return v.value_;
}
template<class T>
class A {
public:
typedef T member_type;
friend member_type fcn< A<T> >(const A<T> &);
A() : value_(1986) {}
private:
T value_;
};
int main()
{
A<int> a;
printf("The value is: %d\n", fcn(a));
}
Notable thing in the above example is that you need to de-couple a cross dependency and make your free-function not depend on a declaration of class A. If you still feel like you need that coupling, the following code works, too:
#include <cstdio>
template <typename T>
class A;
template <typename T> typename A<T>::member_type fcn(const A<T> & v) {
return v.value_;
}
template <typename T>
class A {
public:
typedef int member_type;
friend member_type fcn<T>(const A<T> &);
A() : value_(1986) {}
private:
member_type value_;
};
int main()
{
A<void> a;
printf("The value is: %d\n", fcn(a));
}
Hope it helps. Good Luck!
This may by now be redundant with someone else's answer, but here's a complete, testable solution. The final function definition is a template specialization of fcn, which will produce a compiler error indicating that A<double>::x is not accessible from fcn<int>, but A<int>::x is accessible.
template<class T> class A;
template <typename U>
typename A<U>::member_type fcn(typename A<U>::member_type);
template<class T>
class A {
int x;
public:
typedef int member_type;
friend typename A<T>::member_type fcn<T>(typename A<T>::member_type);
};
template<>
int fcn<int>(int x)
{
A<int> i;
A<double> d;
i.x = 0; // permitted
d.x = 0; // forbidden
return 0;
}
I have this setup:
class DontUse;
template<class T,class U = DontUse, class V = SomeStandardType>
class Foo
{
public:
void bar(U &uh);
};
When U is set to DontUse, I want bar to be an empty function. In all other cases, I want bar to have some implementation. I tried doing this using specialization, but this code (which I realize is somehow incorrect) doesn't compile:
template<class T,class V> void Foo<T,DontUse,V>::bar(DontUse &none){}
template<class T,class U,class V> void Foo<T,U,V>::bar(U &uh)
{
//do something here
}
The error message is this (MSVC10):
1>path_to_project: error C2244: 'Foo<T,U,V>::bar' : unable to match function definition to an existing declaration
and it points to the line of the first template specialization.
How do I do this correctly?
Here's the actual code, although it's reduced to the minimalist part that's relevant:
struct DontUse;
template<typename Derived, typename Renderer = DontUse, typename TimeType = long>
class Gamestate
{
public:
void Render(Renderer &r);
};
template<typename Derived, typename TimeType> void Gamestate<Derived, DontUse,TimeType>::Render( DontUse){}
template<typename Derived, typename Renderer, typename TimeType> void Gamestate<Derived,Renderer,TimeType>::Render(Renderer &r)
{
static_cast<Derived*>(this)->Render(r);
}
You cannot specialize individual members of a template. You have to specialize the class itself:
class DontUse;
template<class T, class V>
class Foo<T, DontUse, V>
{
public:
void bar(DontUse)
{ }
};
I recommend to just use this:
#include <type_traits>
template <class A, class B, class C>
struct S
{
void foo(B& b)
{
static_assert(!std::is_same<U, DontUse>::value, "Bad Boy!");
}
};
Or, if you really want a empty function, just use an if.
#include <type_traits>
template <class A, class B, class C>
struct S
{
void foo(B& b)
{
if(!std::is_same<U, DontUse>::value)
{
//all code goes here
}
}
};
It doesn't work like that. A member function of a class template is not itself a separate template, and cannot be specialized (partially or fully) independently of the class template.
You need to define a partial specialization of the class template Foo, give it a bar member function, and define that.
template <class A,class B>
class H {
public:
A a;
B b;
void fac();
};
template <class B,class A>
void H<B,A>::fac() {
}
What does which follows H exactly mean ?
Since I declared template <class B,class A>, <B,A> seemed to be meaningless....
Can anybody help me ?? Thnx!!
There's no language rule preventing you from doing something like
template<class B> void H<B, B>::fac() {
}
and indeed it may be necessary for any explicit or partial specializations. However, since the vast, vast majority of template code is directly inline, it's really of little consequence.
For example:
template<class A, class B>
class H
{
public:
A a;
B b;
void fac();
};
template<class A> class H<A, A> {
public:
A a, b;
void fac();
};
template<class A, class B> void H<A, B>::fac() {
}
template<class B> void H<B, B>::fac() {
}
Typically, you put the template implementation in the template declaration itself:
template<class A, class B>
class H
{
public:
A a;
B b;
void fac()
{
// Implementation
}
};
However, it is also possible to separate it out:
template<class A, class B>
class H
{
public:
A a;
B b;
void fac();
};
template<class A, class B>
void H<A, B>::fac()
{
// Implementation
}
These two snippets mean the same thing. It's just how the C++ syntax works. Note that the identifier H in the first code snippet doesn't refer to an actual class; it refers to a template class, which is different from a normal class. H is the identifier of a family of classes that are similar but uses different template parameters. That's why you have to say H<A, B> and not just H.
Think about how it usually works for non-template classes:
class NonTemplateH
{
public:
int a;
short b;
void fac();
};
void NonTemplateH::fac()
{
// Implementation
}
You can see how they are similar.
The difference between
template <class A, class B>
void H<A, B>::foo()
and
template <class A, class B>
void H::foo()
is that in the second case foo is a function template inside a non-template class H.
You can only use H without the template arguments at the class scope of H. That part of the definition still belongs to the global scope, where you have to explicitly say what H is.
You asked:
Since I declared template <class B,class A>, <B,A> seemed to be
meaningless....
No, that is not meaningless. To understand that, consider this code:
template <class A,class B>
class H {
template<class C> //note this line!
void fac();
};
Note: Now, fac() is a function template. You've to define it like this:
template <class A,class B> //as usual.
template <class C> //notice this line especially! (not so usual)
void H<A,B>::fac()
{
//your code
}
H<A,B> is needed because it tells the compiler that A and B are template parameters to the class template H, NOT to the function template fac(). C is the tempate parameter to the function template. Notice, I didn't write fac<C>() in the definition. Compiler automacally understands it.
Also, you can interchange the symbol A and B. But if you do this, then do this consistently.
I am trying to create a list object, with the iterator class nested inside to understand how it works.
In some method, I am trying to return an iterator object but it doesn't work.
I created an example to show the problem :
// CLASS A
template <class T>
class A
{
public:
class B;
A(){}
};
// CLASS B
template <class T>
class A<T>::B
{
private:
int varB;
public:
B(B& b);
B(const int&);
B returnThis();
};
template <class T>
A<T>::B::B(const int& value)
{
varB = value;
}
template <class T>
A<T>::B::B(B& b)
{
varB = b.varB;
}
template <class T>
A<T>::B A<T>::B::returnThis()
{
return *this;
}
// MAIN
void main()
{
A<int>::B classB(10);
}
The error is near those lines:
template <class T>
A<T>::B A<T>::B::returnThis()
The compiler tells me I am missing a ; before A::B::returnThis()
I am trying to solve this problem for days and I can't find a way to make it work...
I would really appreciate some help.
Thanks in advance!
You need typename:
typename A<T>::B
To indicate to the compiler that A<T>::B is a type. Here's a good explanation why.
What B is depends on what A<T> is, this is called dependency. Any time you are getting a type out of a class or struct, and it's dependent on a template, you'll need to use typename.
Is there a partial specialization for template class method?
template <class A, class B>
class C
{
void foo();
}
it doesn't work to specialize it like this:
template <class A> void C<A, CObject>::foo() {};
Any help?
If you are already have specialized class you could give different implementation of foo in specialized class:
template<typename A, typename B>
class C
{
public:
void foo() { cout << "default" << endl; };
};
template<typename A>
class C<A, CObject>
{
public:
void foo() { cout << "CObject" << endl; };
};
To specialize member function in Visual C++ 2008 you could make it template too:
template<typename A, typename B>
class C
{
template<typename T>
void foo();
template<>
void foo<CObject>();
};
The solution above seems to will be available only in future C++ Standard (according to draft n2914 14.6.5.3/2).
I think there is a misunderstanding there.
There are two kinds of templates:
the template classes
the template methods
In your example, you have a template class, which of course contains some methods. In this case, you will have to specialize the class.
template <class A>
class C<A,CObject>
{
void foo() { ... } // specialized code
};
The problem in your example is relatively simple: you define the method foo for the specialization C but this specialization has never been declared beforehand.
The problem here is that you have to fully specialize your C class (and thus copying a lot of data). There are a number of workarounds.
Inheritance (Composition ?): do all the common work in a base class, then have the C class inherits and specialize as appropriate
Friend: instead of having the 'foo' method being a member of C, define it as a friend free functions and specialize only this method
Delegation: have your 'foo' method call another method 'bar', which is a free function, and specialize 'bar' appropriately
Which in code gives:
// 1- Inheritance
template <class A, class B>
class CBase
{
// Everything that does not require specialization
};
template <class A, class B>
class C: public CBase<A,B>
// depending on your need, consider using another inheritance
// or even better, composition
{
void foo(); // generic
};
template <class A>
class C<A,CObject> : public CBase<A,CObject>
{
void foo(); // specialized
};
// 2- Friend
// note the change in signature:
// - now you need to pass the attributes to be changed
// - the last parameter helps differentiating the overload
// as there is no specialization for functions
template <class A, class B> void foo(Arg1&, Arg2&, const B&);
template <class A> void foo(Arg1&, Arg2&, const CObject&);
template <class A, class B>
class C
{
friend template <class, class> foo;
};
// 3- Delegation
// same signature as foo in (2)
template <class A, class B> void bar(Arg1&, Arg2&, const B&);
template <class A> void bar(Arg1&, Arg2&, const CObject&);
template <class A, class B>
class C
{
void foo() { bar(member1, member2, B()); }
};
Hope it clarifies, and helps!
No, there is no partial function template specialization in C++0x to be added.
As correctly mentioned above, with regards to function templates basically 2 things were done:
default template arguments were made available;
variadic templates were introduced.
So as before, workarounds should be used to "emulate" partial function templates specialization.
Since the class is the template, you need to specialize that:
template <class A>
class C<A, CObject>
{
void foo() { ... }
}
If I remember correctly, you cannot make partial template specialization for functions. Not sure whether it is included in C++0X
Update:
(Awaiting confirmation) As noted in the comments, partial template specialization of functions is possible in C++0X.
A method template may delegate to (static) methods of partially specialized classes or structs. Template parameters in the outer class are not helpful for answering the question.
class ClassWithSpecializedMethodEmulation
{
private:
template <typename A, typename B> struct Calculator;
public:
template <typename A, typename B> A evaluate(A a, B b)
{
return Calculator<A,B>::evaluate(a,b);
}
private:
template <typename A, typename B> struct Calculator
{
// Common case: multiply
static A evaluate(A a, B b)
{
return (A)(a*b);
}
};
// with double argument a do something else
template <typename B> struct Calculator<double, B>
{
static double evaluate(double a, B b)
{
return (double)(a - b);
}
};
};
In case the method requires access to class members, struct Calculator additionally must be friend of ClassWithSpecializedMethodEmulation and get a this-pointer passed.