A puzzle while learning Templates in C++ - c++

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.

Related

c++ templates and inner classes

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

C++ template argument deduction/substition failed

I'm using a template library in which class B is a templated class parametrized by class A. I have a declaration
template <class A, template <class A> class B>
void foo(){
B<A> x;
}
later on I want to invoke this as
foo<A, B>();
where X is a concrete class in the library and Y is a particular templated concrete class in the library. However, I get the titled error abour template argument deduction/substitution failed. If I change the declaration of foo to remove the templates and subsitute in X and Y, then it all works ok. I also tried
foo<X, Y<X> >();
which failed with the same message. Can someone explain why this is happening?
I'm using gcc 5.3.0
Here's a complete example which gives the indicated behavior
#include <vector>
template <class A, template <class A> class B>
void foo() {
B<A> x;
}
void bar() {
foo<int, std::vector>();
}
You have two issues that I can see.
First is that std::vector takes more than one template argument so the template template parameter template<class A> class B will never match std::vector.
Second and slightly less of an issue is that the class A here template<class A> class B shadows the previous class A here template <class A/*here*/, template <class A> class B>
To fix both of these issues you can declare the second template argument as an nameless variadic template like so: template <class...> class B.
Combining everything you get:
#include <vector>
template <class A, template <class...> class B>
void foo() {
B<A> x;
}
void bar() {
foo<int, std::vector>();
}
Edit:
If you would like to only use B in the form of B<A> you could do one of a few things:
template <class A, template <class...> class B>
void foo() {
using C = B<A>;
C x;
}
OR:
template <class A, template <class...> class B, class C = B<A>>
void foo() {
C x;
}
OR (depending on the larger point of your code) you could just accept the whole thing as one template parameter:
template <class A>
void foo() {
A x;
}
void bar() {
foo<std::vector<int>>();
}
std::vector is not templated on one class, so it does not match your type. You can coerce it to match by
template <class X> using MyVector = std::vector<X>;
and that will work. C++17 will just plain fix this to work as you expected it to.

Injecting template constructor

I have this template, which ends up having a really long, awkward name:
template <class A>
struct foo {
template <class B>
struct bar {
template <class L>
struct baz {
template <int N>
class MyTemplate {
public:
MyTemplate(A a, B b);
};
};
};
};
The nested structure makes sense in the implementation (hidden from this toy example), so I don't want to change it. Now every time I want to use the template, I need to write foo<int>::bar<float>::baz<float>::MyTemplate<5>. I know I can do:
template <class A, class B, class L, int N>
class MyTemplate_Shortcut : public foo<A>::bar<B>::baz<L>::MyTemplate<N> {
// ...
};
The problem is that the constructor of MyTemplate is now hidden. Unfortunately, different instantiations may have different constructor signatures, so it is impossible to write one constructor to call them all. I could also do this:
template <class A, class B, class L, int N>
struct MyTemplate_Shortcut { {
typedef foo<A>::bar<B>::baz<L>::MyTemplate<N> MyTemplate;
};
And now I can do MyTemplate_Shortcut<int, float, float, 5>::MyTemplate, which is better but not quite perfect. Is there any trick, such as CRTP or similar to inject a constructor of MyTemplate into MyTemplate_Shortcut? I know that in C++11, there is a simple solution with template alias:
template <class A, class B, class L, int N> using MyTemplate_Shortcut =
foo<A>::bar<B>::baz<L>::MyTemplate<N>;
Note that I'm not particularly sure about the syntax as I have not used it before. Is there a non-C++11 way to do this?
I'd propose the following solution, which uses a typedef for shortcutting the nested template classes.
...
template <class A, class B, class L, int N>
struct MyTemplate_Shortcut {
typedef class foo<A>::bar<B>::baz<L>::MyTemplate<N> Type;
};
MyTemplate_Shortcut<int, long, float, 5>::Type instance(5, 17);

How do I specialize this template member function?

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.

C++ partial method specialization

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.