Override template class in C++ - c++

I followed this example on how to override a template class in C++ with a specific template, but the Visual Studio compiler keeps complaining about some sort of syntax error. This is my code:
enum LFOType {
LIFO,
FIFO
};
template<typename DataType, LFOType Behavior, int MaxElems = 10>
class LFO {
public:
virtual DataType& top();
}
#include <string>
#include "LFO.h"
template<int MaxElems = 10>
class StringFIFO : public LFO<std::string, FIFO, MaxElems> {
public:
virtual ~StringFIFO() {};
};
Now I'm trying to override the function top() in the StringFIFO-class, but I cannot get it to work. So this is what I tried:
template<int MaxElems = 10>
class StringFIFO : public LFO<std::string, FIFO, MaxElems> {
public:
virtual ~StringFIFO() {};
std::string top() override;
};
Or instead of first overriding the declaration, just overriding it directly in the cpp-file:
template<int MaxElems>
std::string StringFIFO<MaxElems>::top<std::string, FIFO, MaxElems>() {
}
But none of these methods work. The compiler complains that 'std::basic_string<char>' is not identical or covariant to return type 'DataType&' of overridden function LFO<DataType, Behavior, MaxElems>::top.
What did I do wrong?

Related

Variadic Template Class not fully expanded

I am trying to create something similar to a type-safe multiqueue. The idea is that when I push an item, it will be added to a queue consisting of objects of the same type.
All the queues will have a common interface(the queue_intf in this case) that will do some processing.
The code I came up is the following:
#include <queue>
#include <vector>
#include <memory>
#include <stdlib.h>
class queue_intf {
public:
virtual void process(void) = 0;
};
template <typename T>
class queue : public queue_intf {
public:
std::queue<T> q_;
static const char* name()
{
return typeid(T).name();
}
virtual void process(void) override {
printf("process: %s\n", this->name());
}
void push(T &a) {
printf("push: %s\n", this->name());
}
};
template <typename...>
class queues {
public:
std::vector<queue_intf *> qs_;
void process(void) {
for (auto q: this->qs_) {
q->process();
}
}
};
template <typename T, typename... Ts>
class queues<T, Ts...> : public queues<Ts...> {
public:
queue<T> q_;
queues() {
this->qs_.push_back(&this->q_);
}
void push(T &v) {
q_.push(v);
}
};
class a {
};
class b {
};
int
main (int argc, char *argv[])
{
queues<a, b> qs;
a ai;
b bi;
qs.push(ai);
qs.process();
qs.push(bi);
}
However when I compile it I get the following error:
main.cc: In function ‘int main(int, char**)’:
main.cc:65:15: error: no matching function for call to ‘queues<a, b>::push(b&)’
qs.push(bi);
^
main.cc:45:10: note: candidate: void queues<T, Ts ...>::push(T&) [with T = a; Ts = {b}]
void push(T &v) {
^~~~
main.cc:45:10: note: no known conversion for argument 1 from ‘b’ to ‘a&’
I was expecting the queue class to have void push(b &v) method, but it seems it doesn't.
Any idea why?
Edit:
Here is a smaller example (no std:vector or anything):
template <typename...>
class queues {
};
template <typename T, typename... Ts>
class queues<T, Ts...> : public queues<Ts...> {
public:
void push(T &v) {
}
};
class a {
};
class b {
};
int
main (int argc, char *argv[])
{
queues<a, b> qs;
a ai;
b bi;
qs.push(ai);
qs.push(bi);
}
To explain this, let's use a simplified example, you have just two classes:
class base {
public:
void method(int *);
};
class derived : public base {
public:
void method(char *);
};
And you attempt to call it:
derived d;
int i;
d.method(&i);
This fails. Name lookup starts at the given derived class, and finds a matching class method with the specified name: method. However its parameter doesn't match, so this is ill-formed. If the derived class had both methods, overload resolution will pick the matching one. But once a class method with the specified name is found any parent class will not be searched for any other methods with the same name. Only if the derived class does not have any methods with the specified name does name lookup continue with the parent class(es).
Putting
using base::method;
In the derived class imports base's method into the derived's namespace, at which point everything works just like with regular overload resolution.
This is why you need a using declaration with your recursive templates. The second derived template imports it from the first one, the next one imports everything from the second derived template, and so on.

Template a virtual method from base class instead of use overloading

I got strange code and have to extend it. But instead of copy paste many many times i decided to create a template. But get caught by a terrible rock.
Here is an example code:
template<typename T>
class anyClass {};
template<typename T>
class Outer : public anyClass<T>
{
public:
using value_t = T;
class Inner
{
virtual void foo(value_t);
};
};
class specializer : protected Outer::Inner
{
virtual void foo(int) override {}
}
I have to extend virtual void foo(value_t) in specializer.
Example:
class specializer : protected Outer::Inner
{
virtual void foo(int) override {}
virtual void foo(float) override {}
virtual void foo(string) override {}
virtual void foo(bar) override {}
// And so on...
}
Question 1: Why works the example, although class specializer : protected Outer::Inner miss a param?
All overloadings do nearly the same. I created already the function.
template<typename anyType>
void meow( anyType )
{
/***/
}
My problem is here:
virtual void foo(anytype value) //<< replace anytype with what?
{
meow<anytype>( value );
}
I need the type Outer::value_T but i don't know how to get it.
Question 2: How can i use meow by calling foo ?
Feel free to ask for more information.
UPDATE
I looked again in the origin code and realised, that i've overlooked an important using/typedef.
The working code looks like:
class specializer : protected Outer<int, float, string, bar>::Inner //Yes a variadic-template
{
virtual void foo(int) override {}
virtual void foo(float) override {}
virtual void foo(string) override {}
virtual void foo(bar) override {}
// And so on...
}
So Question 1 is solved.
Why works the example, although class specializer : protected Outer::Inner miss a param?
The example does not work. It does not work because Outer is not a type. Also, you override multiple overloads of foo even though inner has only one foo. There are several syntax errors too. If it appears to work, then the compiler is doing something non-standard.
About your second question:
virtual void foo(anytype value) //<< replace anytype with what?
You replace it with the type whose overload you intend to override. For example, if you intend to override foo(int), then replace anytype with int.
Question 2: How can i use meow by calling foo ?
Simply call meow in foo.
You would have to make specializer a template class.
#include <iostream>
template<typename T> void meow(T x)
{
std::cout << x << std::endl;
}
template<typename T>
class anyClass {};
template<typename T>
class Outer : public anyClass<T>
{
public:
using value_t = T;
class Inner
{
virtual void foo(Outer<T>::value_t);
};
};
template<typename T>
class specializer : protected Outer<T>::Inner
{
virtual void foo(T x) override
{
meow(x);
}
};
I wonder how this would help you to change the behavior in Outer or anyClass because you have not shown code which shows where and how Inner is actually used. Without that, it's just guessing.
I have the feeling that what you are actually trying to achieve is to pass a function (or Strategy?) to you Outer class, represented by Inner in your code. That would be better done by passing it as a template argument.
template<typename T>
class anyClass {};
template<typename T, typename Inner = meow<T>>
class Outer : public anyClass<T>
{
public:
using value_t = T;
// somewhere in your code
Inner i;
i.meow( any_value );
};
You can also pass a std::function to the constructor.
template
class anyClass {};
template<typename T>
class Outer : public anyClass<T>
{
public:
using value_t = T;
Outer( std::function<void (value_t)> inner);
// somewhere in your code
i.meow( any_value );
std::function<void (value_t)> i;
};
Originally I simplyfied a little bit to much.
Here is the compileable example of my problem: http://ideone.com/9U7J1a
I removed all unconducive code. I know the design is horrible but i have no influence on it.
class bar {};
class string {};
template<typename _T>
class ModelContainer
{
public:
using value_type = _T;
class Delegate {
public:
virtual void foo( value_type value);
};
};
template< typename... _Ts >
class ModelManager__AbstractBase : protected ModelContainer< _Ts >...
{
public:
class Delegate : public ModelContainer< _Ts >::Delegate... {
public:
virtual ~Delegate( ) = default;
};
};
using ModelManager__Base = ModelManager__AbstractBase<
int,
float,
string,
bar
>;
class ModelManager : public ModelManager__Base {
/* Some functions */
};
class spezializer : ModelManager::Delegate
{
public:
virtual ~spezializer() = default;
//Uncommend to see my error
// virtual void foo( value_type value) override // << value_type unknown
// {/* Calling everytime the same method, no matter which value_type*/}
};

'PolishStack' is not a class template, virtual function ghost error

I'm having some problems implementing a class based on a abstract parent class. It's saying PolishStack is an abstract class, even though all virtual functions are coded:
In file included from braincalc.cpp:10:
./polstack.h:15:7: error: explicit specialization of non-template class 'PolishStack'
class PolishStack<T> : public AbstractStack<T> {
^ ~~~
braincalc.cpp:13:21: error: variable type 'PolishStack<char>' is an abstract class
PolishStack <char> stk;
^
./abstractstack.h:53:16: note: unimplemented pure virtual method 'isEmpty' in
'PolishStack'
virtual bool isEmpty() const = 0;
Here's my class header:
#ifndef POLSTACK_H
#define POLSTACK_H
#include <iostream>
using namespace std;
#include "abstractstack.h"
template <typename T>
class PolishStack<T> : public AbstractStack<T> {
T* data;
int mMax;
int mTop;
public:
PolishStack();
bool isEmpty();
const T& top() const throw (Oops);
void push(const T& x);
void pop();
void clear();
//my funcs:
void printStack();
~PolishStack();
};
#endif
I don't want to give all my code away due to other students cheating, so I'll post the function that the error is complaining about:
#include "polstack.h"
//...
template <typename T>
bool PolishStack<T>::isEmpty() {
if(mTop == 0)
return true;
return false;
}
//...
As others have stated it should be:
template<typename T>
class PolishStack : public AbstractStack<T>
./abstractstack.h:53:16: note: unimplemented pure virtual method 'isEmpty' in
'PolishStack'
virtual bool isEmpty() const = 0;
You're missing the const:
template<typename T>
bool PolishStack<T>::isEmpty() const
// ^^^^^
{
if(mTop == 0)
return true;
return false;
}
Note: You should use the override keyword to be informed when you try to override a function using a different signature (i.e., you're introducing a new function overload instead of overriding the virtual one).
template<typename T>
class PolishStack : public AbstractStack<T>
{
public:
...
bool isEmpty() const override;
...
};
It's hard to tell without all the code, but one thing I noticed is that this:
class PolishStack<T> : public AbstractStack<T> {
should be just:
class PolishStack : public AbstractStack<T> {
That'll fix the first error for sure and potentially (but maybe not) the second.
Try changing to
template <typename T>
class PolishStack : public AbstractStack<T>
As a side note: Exception specifiers throw (Oops) are deprecated.

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)

Returning a derived class of a virtual class in C++

here's my problem.
I have a template abstract class RandomVariable with pure virtual function operator()()
template<T>
class RandomVariable<T> {
public:
virtual T operator()() = 0;
/* other stuff */
protected:
T value;
}
I also have a template abstract class Process with pure virtual function operator()()
template<T>
class Process<T> {
public:
typedef std::pair<double, T> state;
typedef std::list<state> result_type;
virtual result_type operator()() = 0;
/* other stuff */
protected:
result_type trajectory;
}
I can easily write a method returning generating a path and returning the last value of my trajectory.
T GenerateTerminalValue() {
this->operator()();
return value.back().second;
};
But it would be much better if, instead of returning type T my function actually returned a functor (ideally derived from RandomVariable) with overloaded operator() generating a path and returning the last value of the trajectory. My best try only led to a Segmentation Fault.
What would be a good way to do this? Thanks.
What about using std::function?
#include <functional>
template<typename T>
class MyClass {
public:
std::function<T()> GenerateTerminalValueFunc() {
return [this]() {
this->operator()();
return value.back().second;
};
}
...
};
Update: If you want to derive from RandomVariable you could try something like this:
#include <memory>
template<typename T>
class TerminalValueOp : public RandomVariable<T>
{
private:
MyClass<T>* obj_;
public:
TerminalValueOp(MyClass<T>* obj) : obj_(obj) {}
T operator()() {
obj->operator()();
return obj->value.back().second;
}
...
};
template<typename T>
class MyClass {
public:
std::shared_ptr<RandomVariable<T>> GenerateTerminalValueOp() {
return std::make_shared<TerminalValueOp<T>>(this);
}
...
};