For the moment, I have a class, of the following form:
template <std::size_t N,
class T,
class Allocator = typename std::conditional<N, void, std::allocator<T>>::type>
class myclass {};
Which is a particular container with the following behaviour:
if N > 0, then the container has a static size of N, and the Allocator template parameter should be void.
if N == 0, then the container is of dynamic size of, and the Allocator parameter will be used.
But I am not satisfied with this design because it does not seem elegant. I would like a solution standard-like or boost-ready. Maybe such a problem has already been encountered for the design of one of the boost libary. If so what solution has been chosen?
Considering the fact that I want to keep a single version of myclass, and not two version static_myclass and dynamic_myclass.
This might be a good use-case for CRTP. Have a base class which does all the important stuff, which asks its derived class for the actual objects:
template <typename Derived, typename T>
class myclass_base_impl {
// generic stuff
// static_cast to Derived& to get actual data
};
Then, you have two versions of it. The dynamic one:
template <typename T>
class myclass_dynamic
: public myclass_base_impl<myclass_dynamic<T>, T>
{
/* stuff that uses std::allocator<T> */
};
And the static one:
template <typename T, size_t N>
class myclass_static
: public myclass_base_impl<myclass_static<T, N>, T>
{
// presumably something like
T data_[N];
};
Related
I'm trying to use a set of template classes with a variadic parameter. I have several options ahead of me that I could choose from. Before any of my templates are declared or defined I currently have these prototypes: I'm familiar with templates but I haven't had much experience with variadic types when working with templates so the syntax does get a little confusing to me at times. Being that they are all empty shells they do currently compile.
template<typename ClassType, typename... Args> class MatrixReference;
template<typename ClassType, typename... Args> class MatrixStorage;
template<typename ClassType, typename... Args> class MatrixAllocation;
I have a User End Class that will use these classes depending on the intentions of use; it is currently an empty shell for now until I get the other classes defined correctly with the appropriate behavior:
template<typename ClassType, typename... Args>
class Matrix {
};
The rest of the class from the prototypes shown above will inherit from a base class so that the above user class will have a container of them such that the container would be: std::vector<std::unique_ptr<MatrixBase>> or std::vector<shared_ptr<MatrixBase>> and the vector will only ever contain 1 of each type from the listed prototypes. For instance vector[0] would contain a MatrixStorage, vector[1] would container a MatrixReference and vector[2] would contain a MatrixAllocation. Each of these classes have different responsibilities as their names suggest. The storage class will contain a raw stack copy of the elements. The reference class will be use to reference those copies. The allocation class will be used when the elements are declared on the heap. The base class looks like this:
template <typename ClassType = void>
class MatrixBase {
protected:
MatrixBase(){}
virtual ~MatrixBase(){}
}; // Matrix
I have also thought about inheriting them from a non template base as this class does nothing but serve the purpose of being able to store different class types into a single container. I may go ahead and change this to a non template type but for now I'm using it as is to stay with the conventions of its derived types.
Now onto the declaration of my class templates: I really only need to use one of them here since all follow the same pattern, but I'll show all 3 anyway since they are currently empty shells.
// Stores All Of The Contents Of The Matrix
template<typename ClassType, typename... Args>
class MatrixStorage : public MatrixBase<ClassType> {
}; // MatrixStorage
// Used To Reference The Storage Class Of The Matrix
template<typename ClassType, typename... Args>
class MatrixReference : public MatrixBase<ClassType> {
}; // MatrixReference
// Used Only When User Wants To Create A Matrix On The Heap
template<typename ClassType, typename... Args>
class MatrixAllocation : public MatrixBase<ClassType> {
}; // MatrixAllocation
The design approach that I'm looking for is that when this class is used it follows the pattern where the first type is always the type of data the matrix will store either it be an int, float, or some other user defined type; the next parameter is where the use of a variadic parameter comes in so that if one instantiates a template as such:
Matrix<float,2,2> mat2x2; // Default constructor making it empty
This will generate a 2x2 sized Matrix of floats
Matrix<int,3,3,3> mat3x3x3;
This would generate a 3x3x3 volumetric matrix of ints
So the variadic template part will always be + integers and the minimal requirement would be Matrix<type, 1> where this would be in a sense a scalar or a single element matrix or a 1x1 matrix.
This is where I'm presented with a few options. I could use the following
size_t... N
unsigned... D
typename... Args
Currently at the moment as you can see it is declared with the last of the choices. So now comes the main question:
If I decided to use the Parameter Pack where I have a helper class as such:
template <typename ClassType,typename... Dimensions>
class DimensionPack {
public:
typename std::tuple<ClassType, std::tuple<Dimensions...> >::type Dim;
const unsigned int numarguments = sizeof...(Dimensions);
};
The question becomes; is there a known way to make the Variadic Parameter of the same type namely either size_t or unsigned int? If so an example would be appreciated or a reference link would help as well; I've searched and haven't found anything helpful that is similar enough to help me through this.
If there isn't I don't mind having to use size_t or unsigned int but I was preferring to be able to use the helper template to pack and unpack the variadic parameters for me this way I don't have to implement that in each and every class.
I also have a 2 other derived classes not shown here but one would be used with logging them to the screen, where the other would be used with reading and parsing from a file and writing out to a file.
Also as a side note: For extremely large data sets or extremely large sized Matrices: I also have this helper class to use for them:
template<typename ClassType, std::size_t bufferSize>
class MatrixBuffer {
static std::vector<ClassType> matrixBuffer = std::vector<ClassType>().reserve( bufferSize );
};
Edit
I forgot to add this to the original question but I'm adding it now for a little more clarity. I do have a need to test each variadic parameter's value to see if it is odd or even and the results of them will be stored into a vector with a size of the amount of parameters storing a 0 for even or a 1 for odd. This is one of the reasons why I was leaning towards the use of a parameter pack because I could just pass it to a helper function that would return back the vector that is needed.
std::size_t... Args and typename... Args are not the same. The first would expect integers like
Matrix<float,2,2> mat2x2;
while the second would expect types instead.
Of course, you could use std::integral_constant, but that'd be more verbose:
template <std::size_t N>
using size = std::integral_constant<std::size_t, N>;
Matrix<float,size<2>,size<2>> mat2x2;
On the other hand you could use std::index_sequence:
template<typename ClassType, std::size_t... Dims>
class Matrix {
using Dimensions = std::index_sequence<Dims...>;
};
Using static_assert it is possible to check at compile time :
template <typename ClassType,typename... Dimensions>
class DimensionPack {
public:
DimensionPack(const Dimensions&... args){
checkType<Dimensions...>(args...);
}
~DimensionPack(){}
private:
template<typename T> void checkType(const T& t) {
static_assert(std::integral_constant<bool, std::is_same<T, size_t>::value>(), "T is not of type size_t");
}
template<typename T, typename... V> void checkType(const T& t, const V&... v) {
static_assert(std::integral_constant<bool, std::is_same<T, size_t>::value>(), "T is not of type size_t");
checkType<V...>(v...);
}
};
Let's say I have several container classes like these:
template<typename T> class Container
{
/* ... */
};
template<typename T, size_t> class Array : public Container<T>
{
/* Fixed-sized Container */
};
template<typename T> class Vector : public Container<T>
{
/* Variable-sized Container */
};
And I have a class which accepts one of these as a template parameter:
template<typename T, template<typename> class U, size_t M> class Polygon
{
U<T> Vertices; // Problem, what if user passes Array (it needs 2 parameters)
U<T, M> Vertices; // Problem, what if the user wants to use a variable-sized container (it needs only 1 parameter)
};
My question is, can I somehow (probably through tricky template parameter magic) make the consuming class accept any type of container (fixed or variable-sized, even with differing template signatures)?
The only guarantees about the template signatures are, if it is a Fixed-sized container it will have 2 parameters <Type, Size> and one if it is a Variable-sized container <Type>
It's way less tricky than you think it is. You can just template on the container itself:
template <class Container>
class Polygon {
Container vertices;
};
This will work for anything that meets your container requirements, be it fixed sized or not.
The problem of choosing the right template arguments for the container gets moved to instantiation point where the parameters and types must be known anyways.
I am writing a kind of sparse matrix implementation, in fact there are 2 distinct implementations: one for light types (i.e. sizeof(T) <= sizeof(int64) and one for heavy types.
Depending on the sizeof(T), I want to instantiate the corresponding class. I have first tested with a superclass that instantiate the HeavyType or the LightType implementation, but this requires both light and heavy to inherit from a common virtual BaseClass, and the generic call class uses one or the other (not very clean) in this way:
template <class T> class Generic{
public:
Generic(){
if (sizeof(T) > TRESHOLDVALUE)
matrix_ = new HeavyType<T>();
else
matrix_ = new LightType<T>();
}
private:
matrix_ * BaseClass<T>;
};
This works, but it is not clean, and the virtualization in BaseClass slows down the execution...
I would like to write only one template class, and specialize it for several types, but I wonder: is it possibile to specialize against a particular value of sizeof(T) (i.e. equivalent to if (sizeof(T) <= sizeof(int64)))? or for an array of possible types (template <> class Matrix<arrayOfPossibleTypes> )?
I would like to avoid the re-writing of the class for int, bool, uint_32, int32 , etc types.
Does anyone have an idea?
PS:
Alternatively, I thought to a pre-compiler macro to select LightType or HeavyType class, but I think it's impossible to use sizeof() within a #if pre-compiler statement.
You're right that it's not possible to use sizeof in a preprocessor directive. And it's not needed, you can specialise on sizeof(T) just fine. In fact, you can specialise right on sizeof(T) <= sizeof(int64):
template <class T>
class Generic{
private:
MatrixType<T> matrix_;
};
template <class T, bool Light = sizeof(T) <= sizeof(int64)>
struct MatrixType;
template <class T>
struct MatrixType<T, true>
{
//light matrix
};
template <class T>
struct MatrixType<T, false>
{
//heavy matrix
};
With std::conditional, you may do something like:
template <class T> class Generic{
public:
using MatrixType = typename std::conditional<(sizeof(T) > TRESHOLDVALUE), HeavyType<T>, LightType<T>>::type;
Generic() {}
private:
MatrixType matrix_;
};
One solution to this problem is std::enable_if (if you're using C++11) or boost::enable_if (if you're using an older standard). You can add an extra dummy template parameter to the template:
template <class T, typename Enable = void> class Generic;
template <class T>
class Generic<T, typename boost::enable_if_c<sizeof(T) > TRESHOLDVALUE>::type>
{
// implementation for "heavy" class
HeavyType<T> matrix_;
};
template <class T>
class Generic<T, typename boost::disable_if_c<sizeof(T) > TRESHOLDVALUE>::type>
{
// implementation for "light" class
LightType<T> matrix_;
};
This would be best if you actually need to have a different implementation for "light" versus "heavy." If all you're looking to do is change the type of the matrix_ member, and all the rest of your implementation stays the same, then you could use std::conditional (or its Boost equivalent, boost::mpl::if_c).
Before I describe the problem I will give you an idea what is the target of my work.
I want to have a template which creates a class ( while do this unrolling a typelist recursively) which derives from all given types in a variadic list of parameters. That works fine. (see below)
Now is my target to provide all parameters to all constructors of the subclasses via an "automatic" created type from the unrolling template. Finally each of the Unroll classes should eat the parameters it needs to create a instance of the given classes. Each of the recursively created template instances should eat one of the parameter packs contained in the TypeContainer.
Before you ask: This code is only academic to learn new features of c++11. :-)
// create a wrapper around tuple to make it constructible with initializer list
template <typename ... T>
class TypeContainer: std::tuple<T...>
{
public:
TypeContainer(T... args):std::tuple<T...>(args...){};
};
// create a template to concatenate some typelists
// ??? is there a already usable template in std:: ???
template < typename ... X >
class TypeConcatenate;
template <typename T, typename ... S >
class TypeConcatenate < T, TypeContainer< S... >>
{
public:
typedef TypeContainer< T, S...> type;
};
// The follwing template unrolls a typelist and creates a recursively
// inherited class.
template <typename ... T> class Unroll;
template < class Base, class Head, class ... Next >
class Unroll< Base, Head, Next...>: public Unroll < Base, Next...>
{
public:
// collect all needed types for the instance creation of all child
// classes.
typedef typename TypeConcatenate<typename Head::Parms, typename Unroll < Base, Next...>::AllParms>::type AllParms;
};
template < class Base, class Head>
class Unroll < Base, Head>
{
// provide first parameter set for the constructor
public:
typedef TypeContainer<typename Head::Parms> AllParms;
};
template < class Base, class ... Next>
class Top : public Unroll < Base, Next...>
{
// I want to have a constructor which accepts
// all parameters for all the sub classes.
public:
template <typename ...T> Top(T... args);
};
// ??? The following lines of code will not compile!!!
// gcc 4.8.1 gives:
// error: ISO C++ forbids declaration of 'Top' with no type
// ??? Why the compiler could not interpret this as constructor ???
template <typename Base, typename ... Next, typename ... T>
Top<Base, Next...>::Top< TypeContainer<T...>>( T... args) {}
class Base {};
class A: public Base
{
public:
typedef TypeContainer<int, float> Parms;
A( int i, float f){}
} ;
class B: public Base
{
public:
typedef TypeContainer< char, int> Parms;
B( char c, int i){}
};
Top<Base, A, B> top {A{ 1,1},B{1,1}};
Questions:
1) Is there maybe a simpler way to determine the parameter list for the class
hierarchy. My way with typedef typename TypeConcatenate<typename Head::Parms, typename Unroll < Base, Next...>::AllParms>::type AllParms; looks a bit hard :-)
2) Because of 1) I have a kind of type container which holds T... and the problem with my constructor arise with the unpacking of the parameter list which is contained in a container. Maybe my solution is much to complex. Nay hint to solve the basic idea?
3) Ignoring that the problems of 1) and 2) are comes from a totally boring design I want to know which I couldn’t specialize the constructor with
template <typename Base, typename ... Next, typename ... T>
Top<Base, Next...>::Top< TypeContainer<T...>>( T... args) {}
For any further discussion: Yes, I know that the parameters should be forwarded and not given as value an so on. But I want to simplify the example which seems long enough for the discussion.
It sounds like you want a variadic forwarding constructor, something like:
template <typename... Ts>
class lots_of_parents : public Ts...
{
public:
template <typename... Args>
lots_of_parents(Args&&... args) : Ts(std::forward<Args>(args))... {}
};
lots_of_parents<A, B> mytop {A{1, 1}, B{1, 1}};
and either (a) the rest of the question is XY problem, or (b) I'm simply not understanding.
EDIT: Missed the question about your constructor. Ignoring for the moment that functions cannot be partially specialized, I think the syntax would look like:
template <typename Base, typename ... Next>
template <typename ... T>
Top<Base, Next...>::Top< TypeContainer<T...>>( T... args) {}
Which still doesn't really make sense, there's no way to deduce TypeContainer<T...> from T... args.
Context
I have a custom comparator that takes another comparator and applies an additional check:
template <template <typename> class Comparator, typename T>
struct SoftOrder : public std::binary_function<T, T, bool> {
bool operator()(const T lhs, const T rhs) const {
return Comparator<T>()(lhs, rhs) && AnotherCheck();
}
};
I have a second class that accepts a comparator, e.g.:
template <template <typename> class Comparator>
class Processor { ... };
It is easy to instantiate a Processor with a standard comparator (e.g. std::less) like so:
Processor<std::less> processor1;
Processor<std::greater> processor2;
However it is not so easy to instantiate with SoftOrder as the compiler correctly complains about the missing second template argument:
Processor<SoftOrder<std::less> > processor3; // <-- Fails to compile
Current Solutions
I have come up with a few solutions prior to posting this question.
First Solution - Lots of Derived Classes
template <typename T>
struct SoftOrderLessThan : public SoftOrder<std::less, T> {};
template <typename T>
struct SoftOrderGreaterThan : public SoftOrder<std::greater, T> {};
The main drawback of this solution is the need to create a new struct every time a new variant is required, e.g.:
template <typename T>
struct SoftOrderLessThan : public SoftOrder<std::less, T> {}; // Never used after the next line.
Processor<SoftOrderLessThan> processor3;
Second Solution - A very specific bind class
template <template <typename> class Comparator>
struct BindToSoftOrder {
template <typename T>
struct type : public SoftOrder<Comparator, T> {};
};
This is slightly better in that we don't need to create the intermediate classes explicitly:
Processor<BindToSoftOrder<std::less>::type> processor3;
The downside is the requirement of a class specialised for this situation which cannot really be generalised by making SoftOrder a template parameter on BindToSoftOrder as this would make it a template<template<template>>> which is not permitted by the standard.
Third Solution - C++11 template aliases
template <typename T>
using SoftOrderLessThan = SoftOrder<std::less, T>;
Nicer than the first option in that it doesn't require the introduction of new classes, however still requires littering the code with this extra code that is only used in passing onwards to another template class:
template <typename T>
using SoftOrderLessThan = SoftOrder<std::less, T>; // Never used again
Processor<SoftOrderLessThan> processor3;
Finally, the question
Is there a generic way to bind my custom comparator to a specific comparator in the following manner?
Processor<SomeCoolMetaTemplateBind<SoftOrder, std::less>::type> processor3;
I believe if all of the template parameters were simple types I could just do something like Processor<boost::mpl::bind<SoftOrder, std::less> >, but the presence of the template type in the template parameter list prevents this from occurring.
An ideal solution would involve C++03, but am happy to hear C++11 solutions as well.
If it's not possible, I hope at least the question was interesting.
Seems like this would work:
template <
template <template <typename> class,class> class U,
template <typename> class X
>
struct SomeCoolMetaTemplateBind {
template <typename T>
struct type : public U<X,T> {
};
};