Template arguments - c++

I have ClassA<ARG_TYPE> and ClassB<ARG_TYPE>. Now I want want to use ClassC, that has common ARG_TYPE and mentioned classes as template arguments.
ClassC<ARG_TYPE, ClassA<ARG_TYPE>, ClassB<ARG_TYPE>> is easy.
But is it possible do declare ClassC<ARG_TYPE, ClassA, ClassB> so that both A and B classes would know to use ARG_TYPE as their template argument?

Yes, it can be done, through the use of "template template arguments".
Declare ClassC as follows :
template<typename Arg,
template<typename T_Arg> class T_ClassA,
template<typename T_Arg> class T_ClassB>
class ClassC
{
typedef T_ClassA<Arg> MyClassA;
typedef T_ClassB<Arg> MyClassB;
// Use MyClassA and MyClassB
};
Use
ClassC<Arg, ClassA, ClassB>
and it should work fine.

It can be done, however I don't like this solution much.
The issue is that suppose I define:
template <class Arg, class Policy> class Polymorph;
which is a generalization of your MyClassA type but whose behavior can be changed (at compile-time) through the use of policies (think Allocator for standard container for example).
Then I just can't use your interface, because my class takes 2 parameters while your specification only works with one...
Therefore, I much prefer the first approach, even if a bit more verbose. In order to benefit from both you have 2 solutions (both involving duck-typing):
you just define a first class using the first approach and then a second class using the second approach which forwards the (now complete) arguments to the first. This way people with template classes that do not match your requirements will still be able to benefit from your work.
it's up to the user to provide the duck-typing for its class so that it creates a one argument class from a several arguments class. Inheritance and template don't mix well though so this may cause issues and I would favor the previous idea (put the burden on the library writer).
This changes with the advent of C++0x: the later solution becomes a template'd typedef which works much better :)
Here is an example in C++0x:
template <class Arg, template <class> class ClassA>
struct MyTemplate
{
typedef ClassA<Arg> classA_type;
};
template <class Arg, class Policy> class Polymorph;
// C++0x required for following declaration
template <class Arg>
typedef Polymorph<Arg, ConservativePolicy> ConservativePolymorph;
typedef MyTemplate<int, ConservativePolymorph> MyTemplateC;
If you don't have C++0x available, shy away from this and re-use the STL way, even if it's more verbose.

Related

C++: Defining a struct that holds containers defined by templates to types defined by the struct [duplicate]

It seems understanding template template parameters will kill me :(, Let me explain what misconception I made in my mind which confuses me:
template<class T>
class B {}; // A templated class
Here is other code:
template<template<class X> class Z = B> // The problem is in this line for me
class BB{};
Note the line in the parameter list of templated class BB, which is:
template<class X> class Z = B
Now, what stops C++ to think that Z is not another templated class Z?
I.e.,
template<class X> class Z {
}
rather than thinking class Z is a templated parameter itself.
Mankarse has answered your question, but I thought I'd chime in anyway.
Template template parameters are just like normal template type parameters, except that they match templates instead of concrete types:
// Simple template class
template <typename Type>
class Foo
{
Type m_member;
};
// Template template class
template <template <typename Type> class TemplateType>
class Bar
{
TemplateType<int> m_ints;
};
If it helps, you can kind of think of them as like function pointers. Normal functions just accept arguments like normal templates just accept types. However, some functions accept function pointers which accept arguments, just like template template types accept templates that accept types:
void foo(int x)
{
cout << x << endl;
}
void bar(void (*f)(int))
{
f(1);
f(2);
}
To answer your question in the comments: template template template parameters are not possible. However, the reason they are not possible is just because the standardisation committee decided that template templates were enough, probably to make lives easier for the compiler implementors. That being said, there's nothing stopping the committee from deciding that they are possible, then things like this would be valid C++:
template <template <template <typename> class> class TemplateTemplateType>
class Baz
{
TemplateTemplateType<Foo> m_foos;
};
typedef Baz<Bar> Example;
// Example would then have Bar<Foo> m_foos;
// which would have Foo<int> m_ints;
Again, you can see parallels in function pointers.
types <=> values
templates <=> functions of values
template templates <=> functions of functions of values
template template templates <=> functions of functions of functions of values
The analogous function to Baz would be:
void baz(void (*g)(void (*f)(int)))
{
g(foo);
}
Where would you use a template template template?
It's pretty far-fetched but I can think of one example: a really generic graph searching library.
Two common algorithms in graph searching are the depth-first search (DFS) and the breadth-first search (BFS). The implementation of the two algorithms is identical except in one regard: DFS uses a stack of nodes whereas BFS uses a queue. Ideally, we'd just write the algorithm once, with the stack/queue as an argument. Also, we'd want to specify the implementation container of the stack or queue, so that we could do something like:
search<Stack, Vector>( myGraph ); // DFS
search<Queue, Deque>( myGraph ); // BFS
But what is a Stack or a Queue? Well, just like in the STL a stack or a queue can be implemented with any kind of container: vectors, deques, lists etc. and could also be stacks of any element type, so our stacks or queues would have the interface:
Stack<Vector, int> // stack of ints, using a vector implementation
Queue<Deque, bool> // queue of bools, using a deque implementation
But Vector and Deque themselves are template types!
So finally, our Stack would be a template template like:
template <template <typename> class Storage, typename Element>
struct Stack
{
void push(const Element& e) { m_storage.push_back(e); }
void pop() { m_storage.pop_back(); }
Storage<Element> m_storage;
};
And our search algorithm would then have to be a template template template!
template <template <template <typename> class, typename> class DataStructure,
template <typename> class Storage,
typename Graph>
void search(const Graph& g)
{
DataStructure<Storage, typename Graph::Node> data;
// do algorithm
}
That would be pretty intense, but hopefully you get the idea.
Remember: template template templates are not legal C++, so this whole graph search thing won't actually compile. It's just a "what if?" :)
This is part of the syntax of the language (which is monstrous and massively context-dependent). If template<class X> class Z occurs in a template-parameter-list then it is interpreted as declaration of a formal parameter Z with the kind (like a meta-type; kinds classify types in the same way types classify values) "template class taking one class argument".
The usage examples in the accepted answer are misleading,
especially for beginners. Granted it's hard to come up with anything that won't be contrived, but we should at least contrive something that doesn't contradict the overall principles. Template parameters should be used only when the user of our interface can't specify the type of the template for one or the other reason, and we need to do it for them. In the Stack example we ask for both Storage and Element, only to instantiate Storage with that very Element, which is entirely unnecessary, the user can easily perform a basic substitution:
Stack<deque<int>> my_stack;
And all the stack needs to do is this:
template <typename Storage>
struct Stack
{
void push(typename Storage::const_reference e) { m_storage.push_back(e); }
void pop() { m_storage.pop_back(); }
Storage m_storage;
typename Storage::reference top() { return m_storage.back(); }
};
It doesn't in any way decide for the user what the element type is, so it does not need the template parameter. Hence the search becomes
template <template <typename> class DataStructure,
template <typename> class Storage,
typename Graph>
void search(const Graph& g, typename Graph::const_reference)
{
DataStructure<Storage<typename Graph::Node>> data;
// do algorithm
}
Here I guess we assume that internal Graph::Node type is not accessible to the user, and search is somehow a friend function of the Graph, which seems to make some sense. However, do we actually need to fill the structure with graph nodes, or simply references to them? Can the user not refer to the nodes in any way? If not, why is it called a graph, and not, say, slow_unordered_set? So lets imagine for a second they have an access to some node reference/pointer type, then they can do this:
search<Stack<vector<Graph::node_ptr>>>(graph, 10);
The function simplifies further to this:
template <typename StackStructure, typename Graph>
void search(const Graph& g, typename Graph::const_reference)
{
StackStructure data;
// do algorithm
}
Gosh darn it, now it's more generic than ever! Do you want to specify an allocator for the storage? No problem, just do it. You instead wanted some statically allocated vector that requires maximum size parameter? Go right ahead. Want to implement the stack from scratch altogether? Well, as long as it quacks like a stack...
Perhaps a more appropriate example
of a template with template parameters would be some class that represents a complex system and uses some Storage template for a bunch of internal structures, and for some reason is parameterized on that Storage template:
template <template <typename> class Storage>
class System
{
Storage<Component_1> components_1;
Storage<Component_2> components_2;
Storage<Component_3> components_3;
Storage<MetaInfo> registry;
public:
// some inane interface
};
If you ask me - this code reeks, but it's not like I wouldn't write it.
Now that we have this semi-appropriate example for a template with a template parameter, we can contrive something for a template with a template parameter that itself has a template parameter: Imagine somehow we end up with like 10 of these System classes that all have the same interface, all parameterized on a Storage template, but otherwise very VERY different. Brace yourselves for the SuperSystem, an even more complicated class, that uses a bunch of our systems, but CRUCIALLY needs to decide itself what Storage templates to use with each system.
template< template< template <typename> class Storage> class System>
class SuperSystem
{
System<Vector> system_1;
System<OtherVector> system_2;
System<List> system_3;
public:
// absolutely bonkers interface
};
We want to specify something down the template hierarchy we're dealing with here, but still leave something up the hierarchy customizable. For some reason we don't know what exact system we will be dealing with, but we know something very specific about all of them, that we absolutely need to go our way. This is an overarching theme with these examples, our goal is not to make things more generic and customizable, but the opposite - we want to lock down certain deeply embedded things.
TL;DR
In my experience you would only encounter good use cases for templates with template parameters when knee deep in a meta programming library. A rule of thumb: if you can recognize this pattern
template<...> struct f { typedef ... type; };
as a type function, then in that mindset you are allowed to use templates with template parameters, and maybe ponder about anything deeper. Otherwise slap yourself on the wrist.

C++ Multiple definitons of member function, based on enum template argument

Consider this code:
template<typename T, SomeEnum mode> struct TC{
T data;
//...
void doStuff();
};
can "doStuff" have more than one definitions based on the the enum value set for the template?
TC<int, SomeEnum::MODE_1> tc1; tc.doStuff(); //do some stuff
TC<int, SomeEnum::MODE_2> tc2; tc.doStuff(); //do some other stuff
(I don't mean save "mode" and make a branch on it but actually multiple definitions.)
You can do tag dispatch. Just provide an overload for each packaged value of the enum:
template<typename T, SomeEnum mode> struct TC{
T data;
//...
template<SomeEnum v>
using tag_type = std::integral_constant<SomeEnum, v>;
void reallyDoStuff(tag_type<SomeEnum::MODE_1>);
void reallyDoStuff(tag_type<SomeEnum::MODE_2>);
void doStuff() { reallyDoStuff(tag_type<mode>{}); }
};
Because the member functions of a class template won't be instantiated unless used, you'd only instantiate one definition of reallyDoStuff (the proper one) for every instance of TC.
When in doubt, prefer function template overloading to specialization. It's usually the superior alternative.
This is, in general, what template specialization is for. If you don't know what template specializations are, you need to read your C++ book first, before reading the rest of my answer.
The only stumbling block here is that individual class methods cannot be specialized, the entire class must be specialized. But there are common approaches around that, such as the following.
Define your member function as just a function call wrapper to a helper template class, like this:
template<typename T, SomeEnum mode> void TC::doStuff()
{
doStuff_helper<T, mode>::doStuff(*this);
}
That's your actual doStuff(). The actual code goes into the helper class.
Define the helper class template as follows (you will need to properly use forward declarations, and other such miscellanea, of course):
template<typename T, SomeEnum mode> class doStuff_helper {
public:
static void doStuff(TC<T, mode> &me)
{
// ...
}
};
Everything that your original class method did, can now be done here, with some obvious differences. This not the actual method of the original class, any more. So, instead of the original this, you have the me reference here to use. And because this is not the actual class method, there will be the usual issues with accessing private or protected class members. But these are minor details that are easily solved on their own merits. The point is that what you can do now, is specialize the whole thing:
template<typename T> class doStuff_helper<T, MODE_VALUE> {
public:
static void doStuff(TC<T, MODE_VALUE> &me)
{
// ...
}
};
This doStuff() can now be something completely different. This is the general approach for turning class methods specializations, which are not allowed, into ordinary, garden variety, class specialization.
There are further refinements on this general approach that are frequently used. One such refinement would be to have this factored out doStuff() itself be nothing more than a wrapper and a method call to me, with the general and the specialized versions invoking different methods in the original template class.
Once you then work out what happens here, with a piece of paper and a pencil, you will discover that what it ends up doing is turning a single call to the original doStuff() class method into calling two different class methods (which would typically be private), depending on the parameter to the original template class. And those two different class methods would essentially be your two different versions of doStuff() that you wanted to have originally, with only the appropriate method being used depending on the template parameter.

Is the only way to "polymorphically" declare a member of a non-specialized template type, by defining a base class?

Suppose we have a templated class,
template<typename Type>
class Container {};
Of course, we can't do this:
struct Foo
{
Container _container;
}
But what if we wanted to do something like it? Is the only way to do this, to define a base class,
class ContainerBase {};
template<typename Type>
class Container : public ContainerBase {};
and store a pointer, like below?
struct Foo
{
ContainerBase* _container;
}
It's simple enough, but it feels weird to have to add a base class solely for that reason, when it seems the compiler should have enough information to imply a set of related specializations. Of course, regardless _container needs to be a pointer, else Foo couldn't resolve to a static size, but
struct Foo
{
Container* _container;
}
doesn't work either.
it seems the compiler should have enough information to imply a set of related specializations.
Nope. Template specializations are totally unrelated except in name, and the name of a type has essentially no bearing on runtime operation. Specializations of a given template usually share a (mostly) common interface, but they could just as well be completely different.
Adding a base class is essential if you want to relate between the specializations. And if they share so much in common, factoring that functionality into the base is a pretty great idea.

Fully specialized class as template function parameter

I have written two different container classes, which have the same interface but use different member data and algorithms to operate on their members. I also have a template function that takes a container and does some useful calculation:
class Container1
{
// implementation here
};
class Container2
{
// implementation here
};
template<typename ContainerType>
void my_function(ContainerType const& container, /* other parameters */)
{
// ...
}
What bothers me is the fact that 'my_function' should only accept Container1 or Container2, but this is not expressed by the code, since ContainerType can be any type. The function is templated by container type since it does the same thing no matter what is the internal implemetation of container.
I am considering a variant where Container1 and Container2 would be full specializations of a template class. Then I could be more specific about the argument of my_function:
template<typename T>
class Container;
// Tags to mark different container types
struct ContainerType1 { };
struct ContainerType2 { };
template<>
class Container<ContainerType1>
{
// implementation
};
template<>
class Container<ContainerType2>
{
// implementation
};
template<typename T>
void my_function(Container<T> const& container, /* other parameters */)
{
}
In the first case, the compilation with a wrong template parameter will fail if 'ContainerType' does not have the interface required by my_function, which is not very informative. In the second case, I would also get a compiler error (failed template parameter deduction) if I supply anything else than Container<ContainerType1> or Container<ContainerType2>, but I like it better since it provides a hint about what kind of template parameter is expected.
What are you thoughts about this? Is it a good design idea or not? Do you think it is worth the change in the code? There are many other functions like my_function in the code and sometimes it is not obvious what kind of template parameters they expect. What are my other options to make my_function more specific? I am aware the existence of Boost Concept Check Library.
For the sake of argument, let's suppose that I don't want to solve the problem by using inheritance and virtual functions.
In case it is relevant to the discussion, the common interface of Container1 and Container2 is imposed by using CRTP. There might be more container classes in the future.
There are a few solutions to this kind of problem.
Your solution (implementing your types as a template specialization) is one, but one I don't particularly like.
Another is the CRTP:
template<typename T>
struct Container {
// optional, but I find it helpeful
T* self() { return static_cast<T*>(this); }
T const* self() const { return static_cast<T const*>(this); }
// common code between every implementation goes here. It accesses itself through self(), never this
};
class ContainerType1: public Container<ContainerType1> {
// more details
};
class ContainerType2: public Container<ContainerType2> {
// more details
};
that is the core of the CRTP.
Then:
template<typename T>
void my_function(Container<T> const& container_, /* other parameters */)
{
T const& container = *(container.self());
}
and bob is your uncle. As a bonus, this provides a place to put common code.
Another option is a tag traits class that marks the types you want to support, like iterator_traits.
template<typename T>
struct is_container : std::false_type {};
template<>
struct is_container<ContainerType1> : std::true_type {};
template<>
struct is_container<ContainerType2> : std::true_type {};
you can even do SFINAE style pattern matching to detect a base type (like how iterators work).
Now your method can test on is_container<T>::value, or do tag dispatching on is_container<T>{}.
I think your first version is do-able.
At the end of the day, you always have to choose the optimum approach. Second one may look like an overkill although it gets the point across.
If you Container classes will both have a common function (let's say Container1::hasPackage() or Container2::hasPackage() and you choose to call it within my_function then it straight away puts your point across that the eligibility to call it is that function itself. After going through many such projects you will start reading the templates in a reverse manner - starting from the template definition - to see what least properties are needed qualify a particular class.
Having said all this, perhaps your question was more suited for Code Review
One example I created on ideone was using your classes but adding a member variable name to them both which is expected by my_function. Of course there may be classes that will support name but the developer may also burn his fingers a few times to realize the idea behind the function.

typedef variable inside same class. Is it a good practice?

Initially I was trying to typedef a template class and I got to the "gotw 79" article.
And I didn't want to create another class so I ended up doing the following. Basically typedef'ing inside the same class. It works obviously. but is it a good practice?
template <typename T,typename L>
class MyClass{
typedef std::tr1::shared_ptr<MyClass<T,L> > shrdPtr;
}
Thank you.
Well, I'm not a big fan of it unless you are designing MyClass to be specifically used only within shared_ptr objects, at which point I would insist that requirement be enforced.
It's a little ridiculous to put typedefs for every unrelated template instantiation that you might use with a given object. Just because you might put MyClass in a shared_ptr is not a good reason to typedef it there. You going to put typedefs for std::vector, map, list, unordered_map, set, deque,....etc, etc, etc?
But if MyClass extends shared_from_this and has private/protected constructors so that it can ONLY be created and immediately assigned to a shared_ptr then...sure...it's part of the interface.
If you're trying to avoid having to type out long parameter lists to instantiate a shared_ptr for a templated type with lots of parameters then a better bet is an EXTERNAL utility object just like shown in the article you cited:
template < typename T >
struct instantiate_shared_ptr { typedef shared_ptr<T> type; };
template < typename after typename > struct my_complex_template {};
typedef my_complex_template<some parameters> mct_1;
typedef instantiate_shared_ptr<mct_1>::type mct_1_sp;
Yes, especially if the name MyClass_sp is referred to in client code.
This is probably good practice, it makes it simpler if you decide to change the underlying class the typedef refers to at a later date and (arguably) saves typos as well as making code easier to read even if it never changes. The particular choice of name here MyClass_sp leaves a little to be desired in my opinion though.
Also it's worth thinking carefully if making the typedef public or private is most appropriate, i.e. is it part of your public interface?
It's good, IMO.
I used it a lot.
If I want to use a container which element is the type of the my template, I typedef it.
Such as,
template <typename T>
class MyClass {
private:
typedef std::list<T> SomeContainerType;
typedef SomeContainerType::iterator IteratorType;
Then if I find any other structure more suitable, such as a vector, I can change the type without touching too much code.
A better solution for smart pointer typedefs is to do them after the class definition in the header:
namespace N
{
class A
{
};
typedef std::tr1::shared_ptr<A> APtr;
}
This keeps your smart pointer defintion near your class definition while preventing you (and any developers using your code) from having to write code like A::APtr a(new A) (which just looks odd).
EDIT: Since he is concerned with a template class:
namespace N
{
template<class T, class L>
class A
{
};
template<class T, class L>
struct A_Instantiator
{
typedef std::tr1::shared_ptr<A<T, L> > APtr;
};
}