How to inherit Template Functions? - c++

I am required to inherit a templated class for a project. This is what it looks like:
LinkedListInterface.h
#pragma once
#include <string>
using namespace std;
template<class T>
class LinkedListInterface
{
public:
LinkedListInterface(void) {}
virtual ~LinkedListInterface(void) {}
virtual void insertHead(T value) = 0;
virtual void insertTail(T value) = 0;
};
That's what they gave us, and now I need to make a class that inherits from that and then does various functions. I can't for the life of me figure out the proper format. This is what I have so far:
LinkedList.h
#include "LinkedListInterface.h"
#include "Node.h"
using namespace std;
class LinkedList : public LinkedListInterface<class T>
{
private:
int listsize;
Node* head;
Node* tail;
public:
LinkedList(void) {}
virtual ~LinkedList(void) {}
void insertHead(T value) {}
void insertTail(T value) {}
};
My issue is that it wont let me use T, it says Incomplete type is not allowed. Any insight on how to inherit this so I can use T would be great!

Your class needs to either be a template itself or derive from a specialized version of LinkedListInterface:
template<typename T>
class LinkedList : public LinkedListInterface<T>
{
...
};
Or:
class LinkedList : public LinkedListInterface<int>
{
...
void insertHead(int value){ }
void insertTail(int value){ }
};

LinkedList needs to be a class template with template parameter T:
template <typename T>
class LinkedList : public LinkedListInterface<T>
{
....
};

Related

C++ workaroud virtual template method

i know there is nothing like virtual template method in C++, but as it seems it is exactly what i need. Is there any workaround i could use? I am thankful for any suggestion.
I would like to add Entities to a vector by a add method, which need to be virtual and also template, how to avoid this?
#include <iostream>
#include <vector>
class EntityBase {
public:
};
class EntityDerived1 : public EntityBase {
public:
};
class EntityDerived2 : public EntityBase {
public:
};
class ContainerBase {
public:
template<typename T>
virtual void add() = 0; // i know this is not allowed!!!
};
class ContainerConcrete : public ContainerBase {
public:
template<typename T>
void add() override { // i know this is not allowed!!!
data.push_back(std::make_shared<T>());
}
void doSecretStuffWithDataHere() {
// ...
}
private:
std::vector<std::shared_ptr<EntityBase>> data;
};
class Engine {
public:
Engine() :
container(std::make_shared<ContainerConcrete>())
{}
ContainerBase& getContainer() {
auto rawPointer = container.get();
return *container;
}
private:
std::shared_ptr<ContainerConcrete> container;
};
int main() {
Engine engine;
ContainerBase& container = engine.getContainer();
container.add<EntityDerived1>();
container.add<EntityDerived2>();
}
Just make add a regular virtual function that takes shared_ptr as a parameter
class ContainerBase {
public:
virtual void add(std::shared_ptr<EntityBase>) = 0;
};
class ContainerConcrete : public ContainerBase {
public:
void add(std::shared_ptr<EntityBase> p) override {
data.push_back(p);
}
// . . .
And then invoke it with make_shared for the desired type:
int main() {
Engine engine;
ContainerBase& container = engine.getContainer();
container.add(std::make_shared<EntityDerived1>());
container.add(std::make_shared<EntityDerived2>());
}
Alternatively you can add a templated overload that invokes make_shared:
virtual void add(std::shared_ptr<EntityBase>) = 0;
template<typename T>
void add() {
add(std::make_shared<T>());
}

How to avoid multiple "using" declarations at non-dependent names in a template class derived from another template class (c++)?

I'm creating an Ordered Linked List derived from a Linked List base class, where both are templated. I know because of the Two-Phase name lookup I've got specify that the variables depend on something, like "this->head", "LinkedList::head" or specify "using LinkedList::head" at the beginning. I prefer using the third one, but when there are a lot of members that are going to be inherited, it becomes very verbose. Is there some way to avoid this?
// Here I have the Base Class
template <typename T>
class LinkedList
{
...
public:
...
template <typename TArg> void push_front(TArg&& v0);
template <typename TArg> void push_back(TArg&& v0);
void pop_front();
void pop_back();
void erase(const LinkedList<T>::Iterator& pos);
void clear();
...
protected:
Node<T>* head;
Node<T>* last;
size_t _size;
LinkedList<T>::Iterator _begin;
LinkedList<T>::Iterator _end;
};
And the derived class
// Here I have the derived class
template <typename T>
class OrderedList : public LinkedList<T>
{
using LinkedList<T>::head;
using LinkedList<T>::last;
using LinkedList<T>::_size;
using LinkedList<T>::_begin;
using LinkedList<T>::_end;
using LinkedList<T>::push_back;
using LinkedList<T>::push_front;
using LinkedList<T>::clear;
...
...
public:
...
};
What can I do to deal with that?
This problem is a necessary evil. If we could have done what this question asks, then we would have lost the ability(not sure if its good) to name members in derived class as the same name in base class.
See how this example works.
#include <iostream>
#include <string>
class A {
public:
int member;
virtual void Set(int value) {
member = value;
}
};
class B : public A {
public:
int member;
void Set(int value) override {
member = value;
}
void Show() {
std::cout << "member: " << member << " A::member: " << A::member << "\n";
}
};
int main()
{
B b;
b.Set(5);
b.Show();
}

Circular dependency in templated inheritance hierarchy

I have a templated Base class that has multiple child classes and provides an abstract execute method. The children implement this method in different manners and may delegate execute calls to objects in the tail vector of the Base class.
In order to chain objects to the tail, the Base class provides some methods (createChild1, createChild2). Here is the code:
base.h
#pragma once
#include <memory>
#include <vector>
template<typename T>
class Child1;
template<typename T>
class Child2;
template<typename T>
class Base {
public:
std::vector<std::unique_ptr<Base<T>>> tail;
virtual void execute(const T &t) = 0;
Base<T> &createChild1() {
auto child = std::make_unique<Child1<T>>();
tail.push_back(std::move(child));
return *tail.back().get();
}
Base<T> &createChild2() {
auto child = std::make_unique<Child2<T>>();
tail.push_back(std::move(child));
return *tail.back().get();
}
};
child1.h
#pragma once
#include "base.h"
template<typename T>
class Child1 : public Base<T> {
public:
virtual void execute(const T &t) {
// do something with t
}
};
child2.h
#pragma once
#include "base.h"
template<typename T>
class Child2 : public Base<T> {
public:
virtual void execute(const T &t) {
// do something with t
// then delegate to t
for (auto &next : tail) {
next->execute(t);
}
}
};
main.cpp
#include <iostream>
#include "child1.h"
using namespace std;
int main(int argc, char **argv) {
Child1<int> c;
c.createChild2().createChild1();
c.execute(10);
return 0;
}
If I try to compile, I get a "implicit instantiation of undefined template 'Child2'" because in Base, the template class Child2 is only forward declared and its body is not known at that moment. Forward declaring Base in front of Child1 and Child2 and including the definitions of Child1 and Child2 in Base does not solve the problem, because then Child2 cannot access tail.
How can I solve this circular dependency? The code in Child1, Child2 and Base can change, but I want to keep the possibility to chain the create calls in main (therefore the create methods must be declared in the Base class).
The solution was prefixing the access to tail with this->. Therefore just child2.h must be changed:
#pragma once
#include "base.h"
template<typename T>
class Child2 : public Base<T> {
public:
virtual void execute(const T &t) {
// do something with t
// then delegate to t
for (auto &next : this->tail) {
next->execute(t);
}
}
};

Can't use struct in derived templated class?

Ok, maybe not the best title, but here's the deal:
I have a templated interface:
template<typename T>
class MyInterface
{
public:
struct MyStruct
{
T value;
};
virtual void doThis(MyStruct* aPtr) = 0;
};
and an implementation:
template <typename T>
class MyImpl : public MyInterface<T>
{
public:
void doThis(MyStruct* aPtr)
{
} // doThis
};
However, the compiler complains:
In file included from MyTest.cpp:3:0:
MyImpl.h:7:17: error: ‘MyStruct’ has not been declared
void doThis(MyStruct* aPtr)
Why is that?
The following compiled for me:
template<typename T>
class MyInterface
{
public:
struct MyStruct
{
T value;
};
virtual void doThis(MyStruct* aPtr) = 0;
};
template <typename T>
class MyImpl : public MyInterface<T>
{
public:
void doThis(typename MyInterface<T>::MyStruct* aPtr)
{
}
};
int main() {
MyImpl<int> t;
}
The main change is that you need to qualify that the MyStruct was defined within MyInterface<T>.
Since the compiler cannot determine what kind of identifier is the templated subtype, you must help it using the typename keyword. (See When is the "typename" keyword necessary? for more details on typename)

C++ interface style programming. Need a way out

template <typename T>
class BaseQueue
{
public :
virtual void push_back(T value) = 0;
//other virtual methods
};
template <typename T>
class BaseDeque: public virtual BaseQueue<T>
{
public:
virtual void push_front(T value) = 0;
//other virtual methods
};
//Realisation
template <typename T>
class VectorQueue: public BaseQueue<T>
{
typedef typename std::vector<T> array;
private: array adata;
public:
VectorQueue()
{
adata = array();
}
void push_back(T value)
{
adata.push_back(value);
}
};
template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>//,
{
void push_front(T value)
{
VectorQueue::adata.push_front(value);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
VectorDeque<int> vd = VectorDeque<int>();//here is a error
int i;
std::cin >> i;
return 0;
}
I have such error: "C2259: 'VectorDeque' : cannot instantiate abstract class ...". How can I fix it? Class VectorQueue has realize every virtual method of BaseQueue class already. But the compiler doesn't know it. The only way I see is to write something like this:
template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>//,
{
void push_front(T value)
{
VectorQueue::adata.push_front(value);
}
void push_back(T value)
{
VectorQueue::push_back(value);
}
//repeat it fo every virtual method of BaseQueue class (interface)
};
But it's awful.
push_back from BaseQueue isn't implemented on the BaseDeque side of the inheritance chain, and thus the childmost class is still abstract.
I think you're trying to force a class relationship here that shouldn't exist. Note how in the standard library deque and vector are distinct container types and things like queue adapt those containers to very precise interfaces rather than trying to inherit.
Even if you solve your diamond issue (or follow #Mark B's advice and keep them separate), you have a few other issues in there:
template <typename T>
class VectorQueue: public BaseQueue<T>
{
typedef typename std::vector<T> array;
private: array adata; // if this is private, VectorDeque can't reach it
public:
// constructors have an initializer section
// member variables should be initialized there, not in the body
VectorQueue()
// : adata() // however, no need to explicitly call default constructor
{
// adata = array();
}
};
template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>
{
void push_front(T value)
{
// if adata is protected, you can just access it. No need for scoping
/*VectorQueue::*/ adata.push_front(value);
// Error: std::vector doesn't have a method push_front.
// Perhaps you meant to use std::list?
}
};
Multiple inheritance and static polymorphism are of help, for instance:
// Abstract bases
template <typename T, typename Val>
class BaseQueue
{
public :
void push_back(Val val)
{
static_cast<T*>(this)->push_back(val);
}
// ...
};
template <typename T, typename Val>
class BaseDeque
{
public:
void push_front(Val val)
{
static_cast<T*>(this)->push_front(val);
}
// ...
};
// Concrete class
#include <deque>
template <typename Val>
class QueueDeque:
public BaseQueue<QueueDeque<Val>, Val>,
public BaseDeque<QueueDeque<Val>, Val>
{
std::deque<Val> vals;
public:
void push_front(Val val)
{
vals.push_front(val);
}
void push_back(Val val)
{
vals.push_back(val);
}
// etc..
};
int main()
{
QueueDeque<int> vd;// no more error
vd.push_front(5);
vd.push_back(0);
return 0;
}