c++ template problem - c++

i have a class which has a template by other purposes:
template<class t>
class MyClass {
public: //of course public...
t foo;
std::string text;
}
and i have another class which method get all kind of these class through the arguments, and want to store the pointer in an array. The class dont want to access the specific (tempalted) parts of the classes only the common attributes/methods.
class Container {
public: //of course public...
MyClass* array; //this is allocated with some magic.
void bar(MyClass& m) {
and want to store the class in a MyClass* array.
}
}
here is the error that argument list for template missing
how can i solve this?

The simplest method would be to make that function a template as well:
template <class t>
void bar(MyClass<t>& m) {
// ...
}
Note that that should probably be const MyClass<t>&, because you don't need to modify it.
Your new code is meaningless. There is no such that as an object of type MyClass, because MyClass is a template. If you want to operate on these classes irrespective of their template argument, then you need to factor out the non-template portions as a base class:
class MyClassBase
{
public:
// polymorphic base classes should always have virtual destructors
~MyClassBase() {}
virtual void some_function() = 0;
};
template <typename T>
class MyClass : public MyClassBase
{
public:
// implement abstract functions
void some_function()
{
// template argument T is available here
}
};
Then you can refer to that base, and when you call a virtual function it will dynamically dispatch:
class Container
{
public:
// no magic: use a std::vector for dynamic arrays
std::vector<MyClassBase*> array; // not by value! avoid slicing
void bar(MyClassBase& m)
{
array.push_back(&m);
}
void baz()
{
array[0]->some_function(); // for example
}
};

How about putting a common base class.
class MyClassCommon {
protected:
~MyClassCommon() { }
public:
std::string text;
};
template<class t>
class MyClass : public MyClassCommon {
public: // of course public...
t foo;
};
class Container {
public: // of course public...
MyClassCommon* array; // this is allocated with some magic.
void bar(MyClassCommon& m) {
/* ... */
}
};

If you want to create a "multi-template" array, you'd better use a non-template class as a base class of a template class. Or you can make a template array and store any objects in it.

the text variable in your class is private so unless you bar function is a method of the class you can't legally use it like that

Related

Trying to point a base class function pointer to a derived class function

I'm trying to implement a strategy pattern. Right now I'm making a vector of function pointers that take in a vector of ints as their type. I called this vector of function pointers "algo". I want each of the function pointers in the vector to point to a different sorting class (merge, bubble, or insertion). My class structure looks like this: Algorithm is the base class, Sort is an abstract class that inherits from Algorithm, and then Merger, Insertion, and Bubble all inherit from Sort. The problem that I'm running into right now is I can't seem to get my mergePointer pointed to the sortFunc() inside the Merger class. When I try to execute my code it says:
main.cpp:59:28: error: use of undeclared identifier 'sortFunc'
mergePointer = sortFunc();
^
I originally figured the problem was scope resolution so I added Merger:: infront of sortFunc() and I got the same error. I'm not to familiar with polymorphism and am not even sure if what I'm trying to do is possible, any thoughts?
class Algorithm{
private:
public:
vector<int> data;
static std::vector<void (*)(std::vector<int>&)> algo;
void (*activeAlgo)(std::vector<int>&);
enum SortingAlgorithms{
Merge = 0, Insertion, Bubble, Last
};
void load(){
void (*mergePointer)(vector<int>&);
mergePointer = sortFunc();
algo.push_back(mergePointer);
}
void select(SortingAlgorithms sort){
}
};
//abstracted class
class Sort: public Algorithm{
private:
public:
virtual void sortFunc() = 0; //pure virtual function
};
class Merger: public Sort{
private:
public:
void sortFunc(){
data = mergeSort(data);
print(data);
}
};
class Insertion: public Sort{
private:
public:
void sortFunc(){
printVec(data);
insertionSort(data);
printVec(data);
}
};
class Bubble: public Sort{
private:
public:
void sortFunc(){
printVector(data);
bubbleSort(data);
printVector(data);
}
};
int main(){
Sort *myAlgo;
myAlgo->select(Algorithm::Bubble);
}
Note that void(*)(std::vector<int>&) can point only to a namespace function or to static member. Pointers to members are class-specific and have to be called with special operator .* or ->*. What you may implement, is a CRTP with virtual base class (stripped of static vector and other bells and whistles for brevity):
#include <iostream>
#include <cstdlib>
class ActorBase
{
public:
// virtual interfaces
virtual void action() = 0;
};
template <class T>
class Actor : public ActorBase
{
protected:
typedef void(T::* FuncPtr)(/* params */);
FuncPtr algo;
public:
void action()
{
/* do call algo for appropriate object by treating this as pointer to T */
(dynamic_cast<T*>(this)->*algo)(/* args */);
}
};
class Concrete : public Actor<Concrete>
{
void bar() { std::cout << "Hello, Concrete!" << std::endl; }
public:
Concrete() { algo = &Concrete::bar; }
};
int main()
{
Concrete a;
a.action();
return EXIT_SUCCESS;
}
Curiously Recurrent Template Actor is very special template which can cast pointer to self to derived class. Still, it can't know anything about Concrete, e.g. typedefs or members. If it required to pass some traits like that, Actor Should be derived from a template class specialized for concrete T, known as trait class.
Not sure that this perverted approach is what actually needed to solve your X problem though, but at least it's syntactically correct. Here is a canonical CRTP.
Note that the call by member pointer requires .* \ -> AND parenthesis, because call operator () got higher priority than .*.

Getting template type from inherited class C++

So I'm trying to populate a custom collection of a class that is inherited from a template class, like so
template<typename T>
class Parent {
public:
T value;
Parent(T val) {value = val;}
}
class ChildA : Parent<int> {
...
}
class ChildB : Parent<double> {
...
}
// ==== Collections ====
template<typename cT>
class ParentCollection {
public:
cT list[10];
}
class ACollection : ParentCollection<ChildA> {
...
}
class BCollection : ParentCollection<ChildB> {
...
}
So I want to add a function to ParentCollection that will allow me to generate and add a new cT type the the list array. This should be inherited by the children. If I was to write this in ACollection or BCollection, it would be something like:
void ACollection::Add(int val) {...}
or
void BCollection::Add(double val) {...}
respectively. However, since these both do the exact same thing except generate different Childrens, I would want to write this in the ParentCollection, but I can't figure out how to do something like:
void ParentCollection::Add(T val) {...}
that is, use the T type from the Parent class template in the parms for ParentCollection. Is something like this possible? Or must I write the add functions separately for both child collections.
Usually it's a good idea to expose the template parameters, because since C++ has no reflection capabilities it's otherwise a hassle to obtain them outside of the class itself:
// inside parent class
using value_type = T;
You can then reference this typedef to specify your member function signature:
void Add(typename cT::value_type val)
You can typedef the T type in the parent class and then use it in a derived class:
template <typename T>
class Base
{
public:
typedef T BaseT;
};
class Derived : public Base<int>
{
public:
static void printBaseType()
{
printf("%s\n", typeid(BaseT).name()); // prints "i"
}
};
Specific instructions for fixing this:
In the Parent class, add: typedef T ParentT
You can then use the type ChildA::ParentT (int) or ChildB::ParentT (double)
In the ParentCollection class, you can expose this again by doing: typedef typename cT::ParentT ParentT
In ACollection, you can then access it as ParentT.
In ParentCollection, you can write the function declaration as: void Add(ParentT val);
The function definition, however, needs to qualify the ParentT type because you are outside of the class scope, so you write: void ParentCollection::Add(ParentCollection::ParentT val) { ... }

Create "new instance of object" method in C++

Is there a way to create an instance of a class, from that class, without using templates?
I need to do somethink like
static classobj* classobj::create (){return new this;}
Now I use class template and pass to template type of creatable class like :
template<class T>
class basic_class {
public:
static T *create(int param) { return new T(param); }
}
and
class A : public basic_class<A> {}
Why not this?
return new classobj;
Or this:
return new decltype(*this);
But please don't do this at all. The pointer returned by your function has unclear ownership semantics. We generally don't need raw pointers nowadays.
If I understand your question correctly, you want to create a non-template class like this:
class Base
{
public:
static (Magic)* create() { return new (Magic); }
}
We would then call this method thusly:
class Derived : public Base {};
Derived* object = Derived::create();
And the question is: what incantation do we substitute for "(Magic)?" Unfortunately, there is no such syntax. Static class methods are just like regular functions. All types involved must be known at the point the function is declared.
Can you elaborate on why you don't want to use templates? Perhaps there's another way to solve your problem.
If I understand your question correctly, then you have to add static create to every class:
class A
{
public:
//to create
static A* create(int param) { return new A(param); }
};
and then do this:
A* ptr = A::create(4);
or better, avoiding memory leaks
std::unique_ptr<A> uptr(A::create(4));
Or, if your issue is to make a "smart" create in the basic_class for any constructor, then do this in C++11:
template <class T>
class base_class
{
public:
template<typename... Params>
static T* construct(Params&&... parameters) { return new T(std::forward<Params>(parameters)...); }
};
class A : public base_class<A>
{
public:
A(const std::string& s) {}
A(int i) {}
};
and so
A::create(std::string("Hey"));
A::create(5);
both work now.
Edit: Base class defines "construct" method. So the above should be
A::construct(std::string("Hey"));
A::construct(5);
Implement a copy constructor first
classobj(const classobj& obj);
then
return new classobj(*this)

class containing a generic type of a child

Is there any possible way that a generic type can be used to contain a child of a base class.
From the assignment given to me, I am to create something similar to the following in structure.
template <class T>
class Fruit {
private:
int count;
int location_id;
T type;
public:
virtual void displayInfo();
};
class Apple : private Fruit<Apple> {
private:
int variety;
public:
void displayInfo() {
printf("Location %i has %i of %s in stock", location_id, count, variety);
}
};
Fruit<Apple> appleinventory[SIZE];
Basically, I think you can't have a template generic type be the same as a derived class. Am I wrong? Is there something similar that would possibly work?
Update:
For the assignment, I believe we are to use inheritance to show use of virtual functions. I've updated the code above. I think this would work, but does NOT need templates to be successful. We have not covered any advanced, redundant inheritance methods in class.
This is perfectly fine, in principle.
Read up about Curiously Recurring Template Pattern (CRTP) for more info on usage of derived class as the instantiating type in a class template that is its base, esp the example about static polymorphism which should look 'curiously' familiar.
template <class Derived> struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Ignoring questions of why you want to do this....you can get some of the way by doing this following:
template <class T> class Fruit
{
private:
int count;
int location_id;
T* type;
};
class Apple : private Fruit<Apple>
{
private:
int seeds;
bool red;
};
Fruit<Apple> appleinventory[SIZE];
Note the T* type is now a pointer to Apple rather than an instance of Apple.

A pointer to abstract template base class?

I cannot figure this out. I need to have an abstract template base class, which
is the following:
template <class T> class Dendrite
{
public:
Dendrite()
{
}
virtual ~Dendrite()
{
}
virtual void Get(std::vector<T> &o) = 0;
protected:
std::vector<T> _data;
};
Now, I derive from this which specifies exact usage of Dendrite.
Now the problem.
How do I create a vector of pointers to the base-class with no specific type, which
I want to specify by pushing elements to it later? Something like:
class Foo
{
public:
...
private:
std::vector<Dendrite *> _inputs; //!< Unfortunately, this doesn't work...
//! Now I could later on push elements to this vector like
//!
//! _inputs.push_back(new DeriveFromDendrite<double>()) and
//! _inputs.push_back(new DeriveFromDendrite<int>()).
};
Is this possible or am I missing something very basic here?
Typically this is done by your template inheriting from an interface class, IE:
template <class T> class Dendrite : public IDendrite
{
public:
Dendrite()
{
}
virtual ~Dendrite()
{
}
void Get(std::vector<T> &o) = 0;
protected:
std::vector<T> _data;
};
and then you're IDendrite class could be stored as pointers:
std::vector<IDendrite*> m_dendriteVec;
However, in your situation, you are taking the template parameter as part of your interface. You may also need to wrap this also.
class IVectorParam
{
}
template <class T>
class CVectorParam : public IVectorParam
{
std::vector<T> m_vect;
}
giving you
class IDendrite
{
...
public:
virtual ~IDendrite()
virtual void Get(IVectorParam*) = 0;
}
template <class T> class Dendrite : public IDendrite
{
...
// my get has to downcast to o CVectorParam<T>
virtual void Get(IVectorParam*);
};
Yes it is possible. Just make sure to provide virtual functions, and virtual destructor. In addition, you can use typeid to get the actual type (as well as dynamic_cast to check the type)