I have that template class that uses a policy for it's output and another template argument to determine the type for it's data members. Furthermore the constructor takes pointers to base classes which are stored in private pointers. Functions of this objects shall take a this pointer to the template class to give them access to the data. In code this looks like this:
class ShapeGenerator;
template <typename PointData, typename OutputPolicy> class ModelCreator {
private:
OutputPolicy output;
ShapeGenerator* shape
std::vector<PointData> data;
public:
ModelCreator (ShapeGenerator *s) : shape(s) { }
void createShape() { shape->generateShape(this); }
};
ShapeGenerator is an interface and shall be implemented. It looks like this:
class ShapeGenerator {
public:
void generateShape (ModelCreator* m) = 0;
};
If I compile this with g++ 4.3.4 (cygwin) I get an error in the ShapeGenerator::generateShape saying 'ModelCreater' is not a type. I put in a forward declaration of ModelCreator but it changed nothing. I played with some combinations of types and parameters, for example passing only the vector and then I got an error message that said something about incomplete types. I guess this is the problem here.
So, is it possible to pass a templated type with without specific arguements? If so, how?
edit:
I'm not bound to the ModelCreator typename. If I have to write it more template-like this isn't problem. But I would like not to specify the types of ModelCreator in the ShapeCreator object. Is that possible?
edit2:
Ok, I guess I was a bit to optimistic with this "design". It would have been nice to just throw in some ingrediences and get a soup. But now the salt has to know about the kind of water in the pot. I'll change the templates to plain old composition. Thanks you guys.
If you want to use the ModelCreator with "free" template parameters, then you have to make ShapeGenerator a template too:
template <typename PointData, typename OutputPolicy>
class ShapeGenerator {
public:
void generateShape (ModelCreator<PointData,OutputPolicy>* m) = 0;
};
or
template <template <typename, typename> class ModelCreator>
class ShapeGenerator {
public:
void generateShape (ModelCreator* m) = 0;
};
The second version takes another template as a parameter. You would use it like this:
ShapeGenerator<ModelCreator<PointDataType,OutPutPolicyType> > shapeGenerator;
You need to make ShapeGenerate a template class as well:
template <typename PointData, typename OutputPolicy>
class ShapeGenerator;
template <typename PointData, typename OutputPolicy>
class ModelCreator {
private:
OutputPolicy output;
ShapeGenerator< PointData, OutputPolicy >* shape;
std::vector<PointData> data;
public:
ModelCreator (ShapeGenerator< PointData, OutputPolicy >* s) : shape(s) { }
void createShape();
};
template <typename PointData, typename OutputPolicy>
class ShapeGenerator {
public:
void generateShape (ModelCreator< PointData, OutputPolicy> * m) = 0;
};
template <typename PointData, typename OutputPolicy>
void ModelCreator< PointData, OutputPolicy >::createShape() { shape->generateShape(this); }
Related
I am trying to inherit the std::vector class template into my membvec class template as public. And I want to use it as e.g. say membvec<float> mymemb(10) with the intention of creating my membvec variable mymemb containing 10 elements.
But I can't figure out how to write the templatised declaration of the public inheritance. What I am doing is the following, but all in vain.
template <typename T, template <typename T> class std::vector = std::vector<T>>
//error above: expected '>' before '::' token
class membvec: public std::vector<T>
{
const membvec<T> operator-() const; // sorry the previous version was a typo
//error above: wrong number of template arguments (1, should be 2)
...
};
I think you're looking for something like the below, but seriously don't do it. If you ever pass your class as its parent std::vector, there is no virtual interface to allow your class to provide any benefit whatsoever. And if you don't need to substitute for a std::vector then there's no need to inherit from it. Prefer free function algorithms or containing the std::vector as a member in your class instead.
#include <vector>
template <typename T>
class membvec: public std::vector<T>
{
// Don't need <T> in class scope, must return by value.
membvec operator+() const;
};
int main()
{
membvec<int> foo;
}
Perhaps you want something like this:
#include <vector>
template <typename T, template <typename T, class Allocator> class Vec = std::vector>
class membvec: public Vec<T, std::allocator<T>>
{
public:
// This is the signature in your question, but it's questionable.
const membvec<T, Vec> &operator+(int x) const
{
// You obviously want to change this.
return *this;
}
};
You can then use it regularly:
int main()
{
membvec<char> foo;
foo + 3;
}
unfortunately my actual template is too full of stuff that is unrelated to my question, so i tried to put everything in a short example. Lets say, I have written the following template:
#include <vector>
template <typename T> class MyTemplate{
public:
typedef void(*MyFunc)(T);
void addFunc(MyFunc f){myFuncs.push_back(f);}
void callFuncs(T value){
for (std::size_t i=0;i<myFuncs.size();i++){myFuncs[i](value);}
}
private:
std::vector<MyFunc> myFuncs;
};
I learned already, that I can specialize this template to behave different when the passed type is a vector, so I wrote this:
template <typename T> class MyTemplate<std::vector<T> > {
public:
typedef void(*MySingleElementFunc)(T);
void addSingleElementFunc(MySingleElementFunc f){
this->mySingleElementFuncs.push_back(f);
}
void callFuncs(std::vector<T> value){
//for (std::size_t i=0;i<myFuncs.size();i++){
// myFuncs[i](value);
//}
for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
for (int size_t i=0;i<value.size();i++){
mySingleElemetnFuncs[i](value[i]);
}
}
}
private:
std::vector<MySingleElementFunc> mySingleElementFuncs;
};
Now my question is, what is the most elegant way (if possible without inheritance) not only to specialize the template for the case of vector< T > but at the same time still being able to use the first templates methods where vector< T > is the template parameter. What I would like to do later is the following
void Func1(int i){}
void Func2(std::vector<int> i){}
MyTemplate<std::vector<int> > myTemplate;
myTemplate.addFunc(Func1);
myTemplate.addFunc(Func2);
Is it possible to achieve this without simply copy&paste all stuff I need from the original template, to do the same also with the specialized version? I guess I will have to use some kind of inheritance. However, I want to avoid something like this:
MyTemplate<std::vector<int> > myTemplate;
// myTemplate.addFunc(Func1); // does not work
myTemplate.addFunc(Func2);
MyVectorTemplate<std::vector<int> > myVectorTemplate;
myVectorTemplate.addFunc(Func1); // works
myVectorTemplate.addFunc(Func2);
i.e. the functionality should be determined only by the type passed to the template but not by choosing the appropriate subclass. Anyhow, I have to admit that I am a bit confused about how to inherit in this case. If it was not a template, I could write something like
class MyVectorClass : public MySingleObjectClass {}
However, the following does not make any sense:
template <typename T> MyTemplate<std::vector<T> > : public MyTemplate<std::vector<T> >
but in some sense, this is what I would like to have.
I am sorry for such a long post and I hope it is more or less clear what is my problem...
EDIT: I just found a mistake in the above code. The loop in the vector template should read
for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
for (int size_t j=0;j<value.size();j++){
mySingleElemetnFuncs[i](value[j]);
}
}
i.e. each registered function should be called once for each entry in the vector. (Otherwise the template does not work if the number of registered functions is not equal to the size of the vector.)
In fact you want add functionality to the specialization, something like:
template <typename T> class MyTemplate<std::vector<T> >
{
public:
typedef void(*MySingleElementFunc)(T);
typedef void(*MyVectorFunc)(std::vector<T>);
void addSingleElementFunc(MyVectorFuncf){
this->myVcetorFuncs.push_back(f);
}
void addSingleElementFunc(MySingleElementFunc f){
this->mySingleElementFuncs.push_back(f);
}
void callFuncs(const std::vector<T>& value){
for (std::size_t i=0;i<myVectorFuncs.size();i++){
myVectorFuncs[i](value);
}
for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
for (int size_t i=0;i<value.size();i++){
mySingleElemetnFuncs[i](value[i]);
}
}
}
private:
std::vector<MySingleElementFunc> mySingleElementFuncs;
std::vector<MyVectorFunc> myVectorFuncs;
};
template <typename T>
class MyTemplateBase {
// generic stuff goes here
};
template <typename T>
class MyTemplate : public MyTemplateBase<T> {
// nothing goes here
};
template <typename T>
class MyTemplate<std::vector<T>> : public MyTemplateBase <std::vector<T>> {
// specialized stuff goes here
}
If you don't want public inheritance you can use private inheritance, but then you would have to explicitly export everything inherited privately:
template <typename T>
class MyTemplate<std::vector<T>> : private MyTemplateBase <std::vector<T>> {
public:
// generic stuff re-exported
using MyTemplateBase<std::vector<T>>::Func1;
using MyTemplateBase<std::vector<T>>::Func2;
// specialized stuff goes here
}
Might still be worth it, as public inheritance is not exactly the most appropriate tool for code reuse.
I think that, since Vector is a template not a class, should be something like:
template<template <typename ...> class T /*= std::vector*/>
class SomeClass
{
T x;
};
I'm basically trying to do what was discussed in Template specialization of a single method from a templated class except that my TClass has multiple template Parameters like this:
template < class KEY, class TYPE >
class TClass
{
public:
:
void doSomething(KEY * v);
:
};
template < class KEY, class TYPE >
void TClass<KEY, TYPE>::doSomething(KEY * v)
{
// do something
}
This works so far, but how do I define a specialized implementation for one template Parameter? I tried adding this:
template < class TYPE >
void TClass<int, TYPE>::doSomething(int * v)
{
// do something if KEY is int
}
but the Compiler complains about "unable to match function Definition to an existing declaration" (VC2010) for that method/function.
As a sidenote: If I specialize both template Parameters at the same time, it works:
template < >
void TClass<int, char>::doSomething(int * v)
{
// do something if KEY is int and TYPE is char
}
but that's not what I want to do.
Any suggestions?
You have to specialize the entire class before you define a method through a partial specialization:
template <typename T, typename U>
class TClass;
template <typename T>
class TClass<int, T>
{
void doSomething(int* v);
};
template <typename T>
void TClass<int, T>::doSomething(int* v)
{
// ...
}
Live demo
You can fully specialize class method but as far as I remember you can't partially specialize it.
You can try partial specialization for the whole class but this will probably involve a lot of duplication.
I have tried to implement a "template template template" - template class to fullfill my needs ( I am quite new in using template metaprogramming). Unfortunately, I have found the following topic too late:
Template Template Parameters
Nevertheless, I need to implement something like listed below.
According to the compiler the last typedef is not working. I am not sure, but I think this is due to the limitation of 3x template restriction. Is there any possibility to bypass a 3xtemplate definition in this simple example?
template < typename TValueType >
class ITTranslator
{
public:
ITTranslator() = 0;
virtual ~ITTranslator() = 0;
virtual void doSomething() = 0;
}
template < typename TValueType >
class TConcreteTranslator1 : public ITTranslator<TValueType>
{
public:
TConcreteTranslator1(){}
~TConcreteTranslator1(){}
void doSomething() {}
}
template < typename TValueType >
class TConcreteTranslator2 : public ITTranslator<TValueType>
{
public:
TConcreteTranslator2(){}
~TConcreteTranslator2(){}
void doSomething() {}
}
template <
typename TValueType,
template < typename TValueType > class TTranslatorValueType
>
class ITClassifier
{
public:
ITClassifier() = 0;
virtual ~ITClassifier() = 0;
}
template <
typename TValueType,
template < typename TValueType > class TTranslatorValueType
>
class TConcreteClassifier1 : public ITClassifier<TValueType,TTranslatorValueType >
{
public:
TConcreteClassifier1() {}
~TConcreteClassifier1() {}
void dodo(){}
}
template <
typename TValueType,
template <typename TValueType> class TTranslatorValueType,
template <template<typename TValueType> class TTranslatorValueType> class TClassifierValueType
>
class ITAlgorithm
{
public:
ITAlgorithm()=0;
virtual ~TAlgorithm()=0;
virtual run() = 0;
}
template <
typename TValueType,
template <typename TValueType> class TTranslatorValueType,
template <template<typename TValueType> class TTranslatorValueType> class TClassifierValueType
>
class TConcreteAlgorithm1 : public ITAlgorithm<TValueType,TTranslatorValueType,TTranslatorValueType>
{
public:
TConcreteAlgorithm1 (){}
~TConcreteAlgorithm1 (){}
run()
{
TClassifierValueType< TTranslatorValueType>* l_classifier_pt = new TClassifierValueType< TTranslatorValueType>( );
// add this object to a internal list...
}
}
int main()
{
typedef TConcreteTranslator1< cvbase::uint32_t > translator_t;
typedef TConcreteClassifier1< cvbase::uint32_t, TConcreteTranslator1> classifier_t;
typedef TConcreteAlgorithm1 < cvbase::uint32_t, TConcreteTranslator1, TConcreteClassifier1> algorithm_t; // not possible
return 0;
}
Thanks a lot, I really appreciate any help!
EDIT:
I have extended my listing (I am pretty sure it will not compile :)) to show the motivation why I am using my weird concept :)
There is really no need to pass template template parameter around
here. Usually you can just take a normal template argument and provide
a reasonable default:
template<typename ValueType>
struct translator {};
template<typename ValueType, typename Translator = translator<ValueType>>
struct Classifier {};
template<typename ValueType,
typename Translator = translator<ValueType>,
typename Classifier = classifier<ValueType, Translator>
>
struct Algorithm {};
This is done the same way for allocator aware containers.
And please do away with the horrible hungarian-notation prefixes.
NB: It seems from your usage of constructors and destructors that you
don't really have a grasp of basic C++. You might want to stay away
from templates before you have understood easier concepts.
Yes it is possible to avoid template template parameters (of any level).
A template is basically a type-level function. You feed it a type, and get another type back.
A template template parameter is itself a type-level function, and a template that accepts such parameter is a higher-order type-level function.
It is possible to implement higher-order type-level functions with member templates, without ever using template template parameters. I'm not really sure you need it for your design, but here's a quick and dirty example:
// regular type, a.k.a. zeroth-order type-level function,
// a.k.a. "type of kind *"
struct N
{
int a;
};
// a first-order type-level function, a.k.a. "type of kind *->*"
// it is wrapped in a regular type
struct B
{
template <class A> struct Impl
{
void foo(A a)
{
int aa = a.a;
}
};
};
// a second-order type-level function
// that accepts a (wrapped) first-order type function
// and also a regular type. the kind of it would be (*->*)->*->*
// it applies its first argument to its second argument
struct Z
{
template <class X, class Y> struct Impl
{
typename X::template Impl<Y> ya;
void bar()
{
ya.foo(Y());
}
};
};
// now this is something: a third-order type-level function
// that accepts a (wrapped) second-order type-level function
// and a (wrapped) first-order type-level function
// and a zeroth-order type-level function
// it applies its first argument to its second and third arguments
// it is also wrapped in a regular type for consistency
// try to figure out its kind
struct T
{
template <class P, class Q, class R> struct Impl
{
typename P::template Impl<Q, R> yb;
void baz()
{
yb.bar();
}
};
};
T::Impl<Z, B, N> tt;
In this case you don't really need to have template parameters, basically the only variable type is TValueType right?
The other types can be resolved on the class body using TValueType.
Something like this:
template <
typename TValueType
>
class TAlgorithm
{
public:
// TTranslator <TValueType> whatever
// TTranslatorValueType <TValueType> whatever
TAlgorithm(){}
~TAlgorithm(){}
}
I'm using my class as a template parameter of one of its parent class, and that parent class uses it in a template argument (though sizeof()).
And the compiler gives me:
error : incomplete type 'Invoker::workerClass {aka MyClass}' used in nested name specifier
Yet the class is well defined in the file. I guess this is because the child class isn't instantiated at the moment of the base class' instantiation, yet that kind of thing happens with CRTP and there's no problems.
The reason I use the child class in the template argument is to do a different function call if the child class has, or doesn't have, a specific function.
Here's a minimal code for testing
/* Structure similar to boost's enable if, to use
SFINAE */
template <int X=0, class U = void>
struct test {
typedef U type;
};
enum Commands {
Swim,
Fly
};
/* Structure used for template overloading,
as no partial function template specialization available */
template<Commands T>
struct Param {
};
template <class T>
class Invoker
{
public:
typedef T workerClass;
workerClass *wc() {
return static_cast<workerClass*>(this);
}
template <Commands command>
void invoke() {
invoke2(Param<command>());
}
/* If the child class has those functions, call them */
/* Needs template paramter Y to apply SFINAE */
template<class Y=int>
typename test<sizeof(Y)+sizeof(decltype(&workerClass::fly))>::type
invoke2(Param<Fly>) {
wc()->fly();
}
template<class Y=int>
typename test<sizeof(Y)+sizeof(decltype(&workerClass::swim))>::type
invoke2(Param<Swim>) {
wc()->shoot();
}
template<Commands command>
void invoke2(Param<command>) {
/* Default action */
printf("Default handler for command %d\n", command);
}
};
template <class T, class Inv = Invoker<T> >
class BaseClass : public Inv
{
public:
template<Commands command>
void invoke() {
Inv::template invoke<command>();
}
};
class MyClass : public BaseClass<MyClass>
{
public:
void swim() {
printf("Swimming like a fish!\n");
}
/* void fly(); */
};
void testing() {
MyClass foo;
foo.invoke<Fly>(); /* No 'void fly()' in MyClass, calls the default handler */
foo.invoke<Swim>(); /* Should print the swimming message */
}
The error happens at the line:
typename test<sizeof(Y)+sizeof(decltype(&workerClass::fly))>::type
So, is there any compiler that supports this, or is this explicitely specified by the standard as an invalid use of templates? Do I have to change the way I'm doing this and find a way around? CRTP is giving me hope the code might be valid, but I'm not sure.
If this really isn't possible, then why exactly, and why does CRTP work?
The solution was, as ildjarn pointed out, to add another level of indirection.
That is done by changing the test function to accept types:
template <typename X, class U = void>
struct test {
typedef U type;
};
And then pass the child class as a template parameter, instead of specifying it from the get go:
template<class Y=workerClass>
typename test<decltype(&Y::fly)>::type
invoke2(Param<Fly>) {
wc()->fly();
}
template<class Y=workerClass>
typename test<decltype(&Y::swim)>::type
invoke2(Param<Swim>) {
wc()->swim();
}
That way the nested specifier is evaluated only when the function is called and not at the class evaluation, and by that time the child class is already evaluated. Plus with the possibility to pass default template argument, we can call the function without any template parameters.
The template is also much more readable now. And the sample code works just fine now:
class MyClass : public BaseClass<MyClass>
{
public:
void swim() {
printf("Swimming like a fish!\n");
}
/* void fly(); */
};
void testing() {
MyClass foo;
foo.invoke<Fly>(); /* No 'void fly()' in MyClass, calls the default handler */
foo.invoke<Swim>(); /* Should print the swimming message */
}