Why use a specialised template class? - c++

This occured in the line of thought following Template specialization or conditional expressions?.
I am using template specialisation in a project of mine and came across this example from Stroustrup: Matrix.h, where he declares a MatrixBase template class
template<class T> class Matrix_base
for common elements and a Matrix template class
template<class T = double, int D = 1> class Matrix
as a "prop" (whatever that is) for specialisations. He declares the constructor as private so that only specialisations can be instanciated. These are declared:
template<class T> class Matrix<T,1> : public Matrix_base<T> {...};
template<class T> class Matrix<T,2> : public Matrix_base<T> {...};
template<class T> class Matrix<T,3> : public Matrix_base<T> {...};
My question is: In this case, what is the advantage of specialisation? Obviously there is no code that the three specialisations have in common, so why not cut out the general template and declare:
template<class T> class Matrix_1<T> : public Matrix_base<T> {...};
template<class T> class Matrix_2<T> : public Matrix_base<T> {...};
template<class T> class Matrix_3<T> : public Matrix_base<T> {...};
?

Because by having the second template parameter, one allows for specializations as well as a general, non-specialized implementation. So
Matrix<float, 1000> m;
might do something reasonable but non specialized, whereas you would have to define a Matrix_1000<T>.
Edit: the first point applies in general, but not to this particular case, where the general case has a private constructor.
Furthermore, it allows you to do stuff like
Matrix<double, SOME_CONSTANT> m;
which you cannot do with your _N solution.

Basically the answer is that you can use the template in generic code. You can use a compile time constant to change the behavior of the program, or you can write generic code that will handle different versions of the Matrix class that could not be handled if the types had different names:
template <typename T, int D>
void print( std::ostream& o, Matrix<T,D> const & m ) { ...
That is, even though you need to explicitly create the different types, the specialization mechanism allows you to provide a single name that can be used generically to manage the different types as if they are just variants of one single type.

Related

C++ Concepts: Checking if derived from a templated class with unknown template parameter

Is there a way to use C++ concepts to require that a class is derived from a templated class, whose template parameter is again a derived class from another templated class.
Example:
template <class T>
class A{};
template <class T>
class B{};
class X{};
class Y : public A<X> {};
class Z : public B<Y> {};
How can I check in B, that T is of the form std::is_base_of<A<X>,T> for some X without specifying what X is?
I don't want to add X to the template paramter list of B, because I don't want to change code at every instance where B is derived from (e.g. the last line with class Z).
If you want to check for specialisations of A specifically, that isn't too difficult.
template <class C>
concept A_ = requires(C c) {
// IILE, that only binds to A<...> specialisations
// Including classes derived from them
[]<typename X>(A<X>&){}(c);
};
The lambda is basically just a shorthand for a function that is overloaded to accept A specialisations. Classes derived from such specialisations also count towards it. We invoke the lambda with an argument of the type we are checking... and the constraint is either true or false depending on whether the call is valid (the argument is accepted).
Then, just plug it in:
template <A_ T>
class B{};
Here it is working live.
Inspired by answer by #StoryTeller - Unslander Monica, I wrote more general concept which is customisable for any expected template class.
However, you might first ask yourself, whether it makes actually sense to restrict the template type? It makes your design less flexible, so that you can't later e.g. inject mock types for unit testing. IMHO it's usually better to write a concept, which requires your type to adhere to some specific contract (contain some member functions, constants, aliases, etc.) rather than to actually be a concrete class.
Having said that, here's the generalised solution:
/**
* #brief Checks if class type Specialisation (the implicit concept
* argument) is indeed a specialisation of TemplateClass type
* (e.g. satisfied for TemplateClass=SomeLibrary and
* Specialisation=SomeLibrary<A, B>). Also accepts classes
* deriving from specialised TemplateClass.
*
* #tparam PartialSpecialisation optional partial specialisation
* of the TemplateClass to be required
*/
template<class Specialization, template<typename> class TemplateClass,
typename ...PartialSpecialisation>
concept Specializes = requires (Specialization s) {
[]<typename ...TemplateArgs>(
TemplateClass<PartialSpecialisation..., TemplateArgs...>&){}(s);
};
Then for your use case:
template <Specializes<A> T>
class B{};
or even require specific partial specialisation of the desired class:
template<typename ...Args>
struct SomeBase {};
struct A {};
struct B {};
template<Specializes<SomeBase, A> BaseT>
struct Container {};
Container<SomeBase<A, B>> {}; // fine, first template arg is A
Container<SomeBase<B, B>> {}; // error, first template arg isn't A
See working live example here.

C++ partial specialization within the inheritance statement?

So I got myself in a pickle with C++ templates. Assuming I got a hierarchy of container-like classes of the form:
template <class T>
class AContainer{
// ...
};
And through inheritance different containers with different internal representations are made:
template <class T>
class AVectorLikeContainer: public AContainer<T>{
// ...
};
And a bunch of hierarchies of operator-like classes which have the form:
template <template <class T> class C, class T>
class AnOperator{
public:
virtual T operator() (const C<T> &c1, const C<T> &c2);
// ...
};
Using inheritance and partial specialization operators like these are made:
template <class T>
class AnOperatorForVectorLike: public AnOperator<AvectorLikeContainer, T>{
public:
virtual T operator() (const AVectorLikeContainer<T> &c1, const AVectorLikeContainer<T> &c2);
// ...
};
Now, a bit later in the project, containers of the form:
template <class T, std::size_t N>
class AStaticSizeContainer: public AContainer<T>{
// ...
};
were introduced. Obviously this sort of breaks the design, since AStaticSizeContainer doesn't match the template <class T> class C part of the template signature of AnOperator. A way to go around this is to introduce a meta-function like so:
template <class T, std::size_t N>
class StaticSizer{
public:
template <class T1>
class SizedStaticContainer: public AStaticSizeContainer<N, T1>{
// ...
};
};
This way, StaticSizer<25>::SizedStaticContainer is a class which matches the template signature template <class T> class C. However, this has a few downsides. The first and obvious one is the need to always use StaticSize<N>::SizedStaticContainer<T> instead of AStaticSizeContainer<T, N> even when T and N are "known". This is caused by the fact that the two are not interchangeable (one is inherited from the other). The second downside is that all constructors of AStaticSizeContainer must be literally copy-pasted for StaticSizer::SizedStaticContainer. I'm sure there are more that I've yet to stumble upon.
So, my questions are the following:
Is there a more elegant way to fix this while conforming to the already laid out interface?
In broader terms, can we specify a partial specialization of a class in a more elegant way?
In narrower terms, do we have the syntax to say something like:
template <class T, std::size_t N>
class AnOperatorForStaticSize: public AnOperator<AStaticSizeContainer<with N = N>, T>{
// ...
};
where by AStaticSizeContainer<with N = N>, I refer to a partial specialization of AStaticSizeContainer with the N from the above template.
EDIT
C++11's alias templates apparently will work, but I need a C++03 alternative.
In the early day of C++ people experimented with a variety of similar approaches and none of them worked out. It is possible that based on the experience of the last nearly 20 years a better approach could be devised but it seems that Generic Programming (introduced in the form of STL) provided a working solution which doesn't have any of the problems you describe. The basic idea to the solution is the fundamental approach to solve problems in computer science: introduce an extra level of indirection. Instead of tying structure to operators, you'd implement operators in terms of a generalized access method to the structure. In STL the structures are sequences, the operators are algorithms, and the glue in between are iterators.

Need advice on type constrain design in class template in C++, v11

I'd like to place a POD type constrain on type parameter T of class template A and then derive another class template B from the satisfactory A. Besides, B is supposed to have different implementation according to constancy of instance of A. The purpose of doing all this is about, well you know, for better type checking before runtime.
All I can figure out is a tentative definition of A
template <typename T, typename POD=void>
class A;
template <typename T>
class A <T, std::enable_if<std::is_pod<T>::value>::type>
{
//blah...
};
so that A can't be instantialized when passing non-POD type, as you might have noticed that partial parameterization does the trick like a type switch.
But I can't figure out how B could be defined. I presume it looks like the following
template <typename A?>
class B;
template <>
B<const A?> : public A?
{
//blah...
};
template <>
B<A?> : public A?
{
//blah...
};
Any brilliant idea?
PS: Personally I tend to be highly critical. But just post how you think this could be done anyway.
There is no brilliant idea if the specializations are going to be completely different. You have to go with this:
template <typename T>
class B;
template <typename T>
class B<const A<T>> : public A<T>
{
};
template <typename T>
class B<A<T>> : public A<T>
{
};
which is almost same as you've written yourself except ? symbol.
You can instantiate this class as:
B<A<int>> x; //it chooses the second specialization
B<const A<int>> y; //it chooses the first specialization
See online demo. Note that you've forgotten typename here:
typename std::enable_if<std::is_pod<T>::value>::type
I fixed that too.
If some code in the specializations are going to be same, then you could do some trick in order to share the common part, but I cannot suggest anything as I don't know what you're going to put in the specializations.

Can I make a template specialisation that inherits from its base?

In other words: Is it possible to make a template specialisation that inherits from its base, like this:
template <class T>
class A{};
template <>
class A<int>:public A<>{};
so that A has all of A's functions?
I'm new here, so I dunno how to format, just in case the code comes up incorrectly.
You can, with a bit of trickery. This pattern is sometimes called “template subclassing” and is used extensively in the SeqAn library.
The trick is to give the base class an additional template argument tag which determines the type identity:
template <typename T, typename Spec = void>
struct A { … };
// inheritance tag:
struct Derived { };
template <typename T>
struct A<T, Derived> : public A<T, void> { … };
Here, void denotes the base (you could also use a dedicated tag Base but void works fine) and Derived, an empty struct, denotes the derived class.
Now you can instantiate and use the templates as follows:
A<int> the_base;
A<int, Derived> the_derived;
the_base.do_something();
the_derived.do_something();
For a real-world example, consider the String class from SeqAn:
String<Dna> some_dna = "GATTACA";
String<Dna, Packed> more_dna = "GATTACA";
The second type derived from the first one, but is a specialisation which packs its characters as tightly as possible (for DNA, this means putting four DNA characters in each byte).

Extending class template

How would I do to extend a template class, for example vector? The below code does not work. The compiler whines about 'Vector' not being a template.
template <typename T>
class Vector<T> : public std::vector<T>
{
public:
void DoSomething()
{
// ...
}
};
Your syntax is wrong; you need to use:
template <typename T>
class Vector : public std::vector<T>
That said, you should not extend the standard library containers via inheritance, if for no other reason then because they do not have virtual destructors and it is therefore inherently unsafe.
If you want to "enhance" std::vector, do so using composition (i.e., with a member variable of std::vector type) or use non-member functions to provide your additional functionality.
This has nothing to do with extending another class. The problem is your own derived class.
You define a class template like this:
template <typename T>
class Vector
{
...
and not
template <typename T>
class Vector<T>
{
...