templated templates

Hello.

Would somebody mind giving a (very) trivial example of where a templated template would be used and appropriate code? As I'm not seeing the purpose of them.

Thank you,
Uni
LVL 3
Unimatrix_001Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Let_Me_BeCommented:
For example this. Your class not only allows selecting data type but also the storage type for the data.
template < typename DataType, template < typename > class Storage >
class SomeClass
{
    Storage<DataType> data;
};

Open in new window

0
Unimatrix_001Author Commented:
My apologies, I'm afraid I'm not seeing the difference between that and this:

template < typename DataType, class Storage >
0
Let_Me_BeCommented:
The difference is that in your example, you require the user to give you a storage compatible with the data type. You can of course do that. The main problem is what happens when the user presents a storage that is semi-compatible (SomeClass<int,vector<double> >). The code might compile and very, very, very bad things might happen (trust me, dark magic here ;-).
0
Become a CompTIA Certified Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

Unimatrix_001Author Commented:
The main problem is what happens when the user presents a storage that is semi-compatible, but couldn't this be done to alleviate the problem:

template<typename Storage>
class SomeClass{
    Storage data;
};
SomeClass<vector<int>>

?
0
evilrixSenior Software Engineer (Avast)Commented:
templated templates are very useful when doing policy driven design. Consider a policy driven shared pointer with threading policies.

template <
	typename ptrT, // The type of pointer
	typename mutexT, // The type of mutex used by the thread policy (could be shared/timed/unique)
	template <typename> class ThreadPolicy // Thead policy (might be single or multi thread)
>
class SharedPointer : ThreadPolicy<mutexT>
{
	// Implementation goes here
};

Open in new window

0
Unimatrix_001Author Commented:
Hi Ricky,

Hm, sadly I'm not understanding the purpose of that - mainly because I know nothing about threads... :(

Thanks,
Uni.
0
evilrixSenior Software Engineer (Avast)Commented:
>> Hm, sadly I'm not understanding the purpose of that - mainly because I know nothing about threads... :(

Ok, well a smart pointer has to be thread safe (in other words it must be protected from 2 threads trying to change it at the same time) and that protection is provided by a mutex (mutual exclusion) object but there are many different types that behave in different ways and have different semantics. Also, they are expensive in terms of performance. By allowing the mutex and the threading policy to be passed seperately we allow the caller to decide if they want a shared mutex (many readers but only 1 writer) or a timed mutex (block for a period of time and if still no access throw an error) or unique (block forever, never give up waiting for exclusive access). Meanwhile, the threading policy will be different depending upon if you know your application uses multipl;e threads or not. If you are using single threads your threading policy will most likely to nothing if it's using multipel threads the policy will implement aggressive mutual exclusion access to critical sections of the shared pointers code. The idea is these related but not bound together policies can be passed in as template param and template template param and they get bound together at the point of instgantiation. This mean, you can have many different smart pointers behaving in different ways to suit your needs all with the use of a simple typedef...

typedef SharedPointer<int, Shared, Multi> SM_SharedPointer;
typedef SharedPointer<int, Unique, S> SS_SharedPointer; // A little pointless maybe?
typedef SharedPointer<int, Timed, Multi> TM_SharedPointer;

It doesn't matter if you don't fully understand the concepts of threading or mutexes. The important thing is it gives you the flexibility to avoid binding things until the point of instantiation so you can implement your template class using policies rather than concrete types.
0
Unimatrix_001Author Commented:
Could you explain the syntax of:
              >> template <typename> class ThreadPolicy
...perhaps that would help me better understand it...?
0
Let_Me_BeCommented:
The problem of SomeClass<vector<int>> is that SomeClass does not see the int (in case of vector it actually does, using vector<int>::value_type, but STL is very specific in this). In most cases you need to see that int as well.
0
evilrixSenior Software Engineer (Avast)Commented:
>> The main problem is what happens when the user presents a storage that is semi-compatible, but couldn't this be done to alleviate the problem:
When writing generic code using templates we use the terms concept and model (something that will be enforceable in C++0X but for now it's a convention). So a concept is something that a template is designed to work with... it's like the interface it expects. A model is something that implements this so it models the concept. If you write a class that allows callers to specify the storage type your class will expect a storage type that models the concept that your class is designed to work with. This is true of all template parameters whether they are template templates or template types.
0
evilrixSenior Software Engineer (Avast)Commented:
>> template <typename> class ThreadPolicy
It basically says, this template parameter is a template class, that I have named Thread Policy, that takes 1 template parameter. It can be instantiated like this...

ThreadPolicy<mutext_type> threadPolicy;
0
evilrixSenior Software Engineer (Avast)Commented:
>> SomeClass<vector<int>>
Will not work with

template < typename DataType, template < typename > class Storage >
class SomeClass
{
    Storage<DataType> data;
};

...because  template < typename > class Storage does not define a concept modeled by a vector. Kudos to who can tell me why this is (if not I'll tell you) :)
0
Let_Me_BeCommented:
Btw. Unimatrix_001, I think you should read Modern C++ Design by Andrei Alexandrescu. It will push your C++ understanding (and specifically templates) a lot further.
0
evilrixSenior Software Engineer (Avast)Commented:
>> read Modern C++ Design by Andrei Alexandrescu
Great book... but I think a little too advanced for Uri (in fact most C++ programmers :) ) right now. I'm thinking C++ Templates by Vandevoorde & Josuttis is a better place to start.
0
Unimatrix_001Author Commented:
Btw, just so you know... reply coming up... :)
0
Unimatrix_001Author Commented:
When writing generic code using templates.....they are template templates or template types.
Ooohhh... My head really hurts. :(


The problem of SomeClass<vector<int>> is that SomeClass does not see the int (in case of vector it actually does, using vector<int>::value_type, but STL is very specific in this). In most cases you need to see that int as well.
Right... That's slightly clearer... So consider the following example::

---------------------------------------------------------------------------------
template<typename TContainerType>
class CStorage{
      TContainerType storageArea;
};
CStorage<vector<int>> object;

will work fine, but the problems within the CStorage class is that it is impossible for me to tell:

      a) What container type I'm using.
      b) What data type that container is using.

which is sometimes good to know, is that correct?
---------------------------------------------------------------------------------

---------------------------------------------------------------------------------
template<typename TContainerType, typename TDataType>
class CStorage{
      TContainerType<TDataType> storageArea;
};
CStorage<vector, int> object;

This too will work fine providing:

      1) The container type I pass in is compatible with the TDataType, of which I have no assurance?

Is that correct?
---------------------------------------------------------------------------------


Kudos to who can tell me why this is
I think you can guess who can't tell you why! ;)


I'm afraid I'm still not quite grasping the concept of having a template within a template. :( I'm trying to get to grips with it by working on the principle of handling a container and it's data type.


template < typename DataType, template < typename > class Storage >

I THINK I see the purpose of this, but I'm still struggling with the syntax. :(


I'm thinking C++ Templates by Vandevoorde & Josuttis is a better place to start.
That reminds me, that should have been delivered today after you recommended it to me a couple of days ago! Must follow that up on Monday....


Thank you,
Uni.
0
evilrixSenior Software Engineer (Avast)Commented:
>> a) What container type I'm using.
typeid(TContainerType)

>> b) What data type that container is using.
typeid(TContainerType::value_type) // assuming the standard STL concept has been modeled.

>> The container type I pass in is compatible with the TDataType, of which I have no assurance
Sure you do... if it wasn't then the compiler would error -- if it doesn't that's your assurance :)

>> I think you can guess who can't tell you why! ;)
Look at the other question I just answered for you... look at how vector is defined (you already now this) and now look at that template template parameter and see what it expects... see the difference? Go on Uri, I know you'll get this.

>> I'm afraid I'm still not quite grasping the concept of having a template within a template
it's just a way of telling the compiler what template type to used rather than it being hard coded into the class. So, if you have a stack, for example, you could implement it with a list or a vector or a dequeue. Each has pros and cons. Your stack can take the concrete type as one template param (the type you wish to store in the container) and the storage container type as the template template. Of course, this could eb done by just taking one concrete type of the container already defined to take, for example an int, but doing it as 2 separate params gives the user more flexibility. The type bing store and the container being used might not be decided in the same part of the calling code so the decision of which of these two to use might happen at different times.

>> I THINK I see the purpose of this, but I'm still struggling with the syntax. :(
You define a template this...

template <typename T>

You define a template template thus

template < template <typename> class TemplateTemplateName >

It's just a template declaration within another template declaration(except the class keyword follows it with the name you wish to give the template template -- this is arbitrary and up to you just like the name of any template parameter.

>> That reminds me, that should have been delivered today after you recommended it to me a couple of days ago! Must follow that up on Monday...
I used to have 2 copies :) I can also recommend C++ Template Metaprogramming (concepts, tools and techniques from Boost and Beyind) by David Abrahams and Aleksey Gurtovey.
0
evilrixSenior Software Engineer (Avast)Commented:

**** Build of configuration Debug for project scratchcpp ****

make -k all
Building file: ../main.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cpp"
../main.cpp: In function int main():
../main.cpp:13: error: type/value mismatch at argument 2 in template parameter list for template<class DataType, template<class T> class Storage> class SomeClass
../main.cpp:13: error:   expected a template of type template<class T> class Storage, got template<class _Tp, class _Alloc> class std::vector
../main.cpp:13: error: invalid type in declaration before ; token
../main.cpp:13: warning: unused variable someClass
make: *** [main.o] Error 1
make: Target `all' not remade because of errors.
Build complete for project scratchcpp

#include <vector>
 
template < typename DataType, template < typename T > class Storage >
class SomeClass
{
    Storage<DataType> data;
};
 
 
int main()
{
	SomeClass<int, std::vector> someClass;
}

Open in new window

0
Unimatrix_001Author Commented:
Ah I may be getting this... Gonna do a bit of reading with the posts above... :)
0
evilrixSenior Software Engineer (Avast)Commented:
No worries Uri.

BTW: The reason I'm letting you figure out my little puzzle is because it will aid your understanding if you can figure it out for yourself.
0
Unimatrix_001Author Commented:
>>The reason I'm letting you figure out my little puzzle is because it will aid your understanding if you can figure it out for yourself.
Thank you. Your help with this is really appreciated! :)
0
evilrixSenior Software Engineer (Avast)Commented:
Uri, off to bed now (3:30am UK time). I'll catch up tomorrow.

Night dude.
0
Unimatrix_001Author Commented:
Hehehe, yep I need to be getting some sleep as well (in the UK as well. ;) Feeling kind of groggy - Let_Me_Be hope you don't mind if I knock off and look at this tomorrow - perhaps a bit of a sleep will help sort things out. :)

Later.
Uni.
0
evilrixSenior Software Engineer (Avast)Commented:
>> in the UK as well.
Which Part? Me, Luton (25 miles north of London).
0
Unimatrix_001Author Commented:
Uurgh... didn't sleep last night - kept thinking about templating templates! :(

>>Which Part?
Newcastle. :)

Anyways, I think I may be a little closer to understanding things... :) So if we've got something like:

     template < typename TDataType, template < typename TNullDataType > class TContainerType >

then TDataType specifies what data type the container (which is specified with TContainerType) will hold. The TNullDataType isn't used at all, but is required because a vector (and most other containers) are declared as follows:

vector<TDataType>

So we need the TNullDataType to satisfy the way containers are declared. What I'm not quite grasping is why we must specify the data type for the container twice, why can't we just use TNullDataType and not have the first parameter (TDataType)?

Thanks,
Uni
0
Unimatrix_001Author Commented:
Also, not quite grasping why we can't have:

     template < typename TDataType, template < typename TNullDataType > typename TContainerType >

Why the need to replace the last typename with class? I know you (evilrix) mentioned it in passing in a previous question but it was not relevant then for it to be explained why.

Thanks,
Uni
0
evilrixSenior Software Engineer (Avast)Commented:
Hey Uri...

Just a quick holding post. I am quite busy today (Saturday's eh?) but I will try and get back to you later.

Meanwhile, here are some links I think might help you out a little...

http://www.informit.com/articles/article.aspx?p=376878
http://www.progdoc.de/papers/ttp/psi-ttp/psi-ttp.html

..I'll try and respond to you fully tonight.

>> Newcastle. :)
Geordie eh? "Shy Bairns Get Nae Sweeties" (apparently that's a Geordie thing to day). Great place to go drinking ;)
0
Unimatrix_001Author Commented:
Ok cheers. Yeah no problem mate take your time. :) Hehehe, well I'm just outside geordie land, but it's the closest place that anybody really knows. Still got a bit of the accent though. ;)
0
evilrixSenior Software Engineer (Avast)Commented:
Right... I'm back. Yesterday was just too busy for me to get online.

>> then TDataType specifies what data type the container (which is specified with TContainerType) will hold
Well, no. It just specifies the type passed in as the first parameter, that doesn't mean it'll be used to define a concrete type of TContainerClass, which could be defined using any type.

TContainerClass<int> intContainer;
TContainerClass<char> charContainer;

>> The TNullDataType isn't used at all
I never bother to specify the name, it's just a signature and the name isn't required...

template < typename TDataType, template < typename > class TContainerType >

...just like with a function signature you can leave of the parameter names...

void foo(int i, float f, char c);
void foo(int, float, char);

>> but is required because a vector (and most other containers) are declared as follows:
heh. that's not how vector is defined. Remember my little puzzle I set you and your question about allocators? But, other than that, yes TContainerClass defines a template template parameter that will accept any template defined thus

TContainer< TParam > // This is NOT how a vector is defined, so vector cannot be used here

But this is not going to work for a vector because a vector has a signature of template<typename valueT, typename allocatorT> vector<valueT, allocatorT> (see code below)

>> What I'm not quite grasping is why we must specify the data type for the container twice
You're not, the first type and the template type are unrelated, just because you might use the template type to define a concrete instance of the container doesn't mean you have too. The type parameter TDataType and the template parameter TContainerType are completely 2 different unassociated entities unless you bind them together in a definition to create a concrete type of TContainerType<TDataType>

template < typename TDataType, template < typename > class TContainerType >
void foo()
{
   TContainerType<TDataType> tContainer; // Now we bind them together (but we don't have to)
   TContainerType<int> intContainer;
}

>> Why the need to replace the last typename with class?
Because that's the syntax... you are not declaring a type here you are declaring a template class

Although often used interchangeably, there is a semantic difference between the template class and class template
http://womble.decadentplace.org.uk/c++/template-faq.html#phrase-order

"Q: Is there a difference between a function template and a template function, or between a class template and a template class?

A: The term "function template" refers to a kind of template. The term "template function" is sometimes used to mean the same thing, and sometimes to mean a function instantiated from a function template. This ambiguity is best avoided by using "function template" for the former and something like "function template instance" or "instance of a function template" for the latter. Note that a function template is not a function. The same distinction applies to "class template" versus "template class". "



#include <vector>
 
template < typename DataType, template < typename T, typename A = std::allocator<DataType>  > class Storage >
class SomeClass
{
    Storage<DataType> data;
};
 
 
int main()
{
	SomeClass<int, std::vector> someClass;
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Unimatrix_001Author Commented:
Hi evilrix,

>>Right... I'm back. Yesterday was just too busy for me to get online.
Hehe, not a problem mate. :)

>>...just like with a function signature you can leave of the parameter names...
I'm not quite sure about this part. If we have:

template<typename, typename>
class A{};

how can class A ever use anything within the template as there are no parameter names to associate with?
0
evilrixSenior Software Engineer (Avast)Commented:
>> how can class A ever use anything within the template as there are no parameter names to associate with?
If it's not being referenced there is no need to name it. Instantiations still have to conform to that signature though. In the case of a template template parameter we're just telling the compiler the template must conform to that signature but since we're not using the template parameters themselves we don't need to provide them.
template<typename A, typename /* never used so it has no name*/ >
class CMyClass{
       A var1;
 
};
 
int main()
{
	CMyClass<int, float> cif;
}

Open in new window

0
Unimatrix_001Author Commented:
Ah okay... Well, most of what you've said I've understood and I should be getting the template book you recommended tomorrow so I shall accept one of your many thorough comments! Got to say your patience is second to none! :)

Thanks very much,
Uni.
0
Unimatrix_001Author Commented:
Thank you.
0
evilrixSenior Software Engineer (Avast)Commented:
Uri, you are very welcome.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.