Deriving from pure virtual template class - c++

I belive my problem is simple, yet I cannot manage to overcome it.
I have abstract template class aghContainer and child template class aghVector. I am trying to make aghVector object, but I get an error that I cannot create objects of abstract class. I am pretty sure that I implemented all methods, but maybe I miss something...
aghContainer:
template <typename T>
class aghContainer {
public:
virtual ~aghContainer() {}
virtual void append(T const&) = 0;
virtual void append(aghContainer<T> const& right) = 0;
virtual bool replace(const int, T const&) = 0;
virtual T& at(const int) const = 0;
virtual int size(void) const = 0;
virtual bool remove(const int) = 0;
virtual void clear(void) = 0;
virtual bool isEmpty(void) = 0;
virtual int indexOf(T const& _value, int _from = 0) const = 0;
virtual bool contains(T const& _value, int _from = 0) const = 0;
virtual void print(ostream&) const = 0;
virtual bool equal(aghContainer<T> const& right) const = 0;
virtual bool operator==(aghContainer<T> const& right) const;
virtual bool operator!=(aghContainer<T> const& right) const;
virtual T& operator[](const int n) const;
virtual aghContainer<T>& operator+=(T const& element);
virtual aghContainer<T>& operator+=(aghContainer<T> const& right);
virtual aghContainer<T>& operator<<(T const& element);
virtual aghContainer<T>& operator<<(aghContainer<T> const& right);
friend ostream& operator<<(ostream&, aghContainer<T> const& right);
};
aghVector:
template <typename T>
class aghVector :
public aghContainer<T> {
public:
aghVector();
~aghVector();
void append(T const&);
void append(aghContainer<T> const& right);
bool insert(const int, T const&);
bool replace(const int, T const&);
T& at(const int) const;
int size(void) const;
bool remove(const int);
void clear(void);
bool isEmpty(void);
int indexOf(T const& _value, int _from = 0);
bool contains(T const& _value, int _from = 0) const;
void print(ostream&) const;
bool equal(aghContainer<T> const& right) const;
private:
T* vector;
unsigned int elements;
void destroyVector();
};
Error:
'aghVector': cannot instantiate abstract class Data-Container G:\CPP\Data-Container\ex3main.cpp 101

A couple of problems I can see on a quick look.
In aghContainer
void append(aghContainer<T> const& right) = 0;
and in aghVector
void append(aghVector<T> const& right);
actually overloads the function with a different argument type (since aghVector is a distinct type from aghContainer. The inherited append() will be hidden and not overridden.
A similar problem for equal().
The declaration of indexOf() in aghContainer is const, and the one in aghVector is not. Therefore, again, the version in aghVecvtor hides the inherited function, and does not override it.

From the aghContainer class you have the function
void append(aghContainer<T> const& right) = 0;
Then in the aghVector you have this function:
void append(aghVector<T> const& right);
The problem is that those are two different functions, which means you don't override the parent class append function. leading to aghVector still being an abstract class.

Related

In template: no matching constructor for initialization in a vector

I making a vector of pairs of custom types, but I can't compile with it...
I am looking to store pointers to Factory functions. Currently I store IOperand* but it doesn't seem to be the right type to put
I made this vector in a class:
class Factory
{
public:
Factory();
static IOperand* createOperand(eOperandType type, const std::string& value);
~Factory();
protected:
private:
static IOperand* createInt8(const std::string& value);
static IOperand* createInt16(const std::string& value);
static IOperand* createInt32(const std::string& value);
static IOperand* createFloat(const std::string& value);
static IOperand* createDouble(const std::string& value);
static IOperand* createBigDecimal(const std::string& value);
std::vector<std::pair<std::string, eOperandType>> operands;
std::vector<std::pair<eOperandType, IOperand*>> operands_factory;
};
My first vector is working fine, but the second isn't working:
Factory::Factory()
{
//Working fine
operands.emplace_back("bigdecimal", BIGDECIMAL);
//emplace_back isn't working
operands_factory.emplace_back(std::make_pair(INT8, &Factory::createInt8));
}
Here is the error from the compiler:
/usr/include/c++/9/ext/new_allocator.h:145:20: error: no matching function for call to ‘std::pair<eOperandType, IOperand*>::pair(std::pair<eOperandType, IOperand* (*)(const std::__cxx11::basic_string<char>&)>)’
My IOperand interface is described as below:
class IOperand
{
public:
virtual std::string toString() const = 0;
virtual eOperandType getType() const = 0;
virtual IOperand* operator+(const IOperand & rhs) const = 0;
virtual IOperand* operator-(const IOperand & rhs) const = 0;
virtual IOperand* operator*(const IOperand & rhs) const = 0;
virtual IOperand* operator/(const IOperand & rhs) const = 0;
virtual IOperand* operator%(const IOperand & rhs) const = 0;
virtual ~IOperand() {}
};
So I really don't know how can I fix it and why...

-Woverloaded-virtual warning for const function

I have this piece of code:
class ISerializable
{
public:
virtual bool operator==(const ISerializable* /*value*/) const { return false;};
virtual bool operator!=(const ISerializable* /*value*/) const { return true;};
};
class Point2I : public ISerializable
{
public:
bool operator==(const Point2I& value)
{
return (x == value.x && y == value.y);
}
bool operator!=(const Point2I& value)
{
return !(*this == value);
}
public:
int x;
int y;
};
class Coordinate : public ISerializable
{
public:
virtual bool operator==(const Coordinate& value) const;
virtual bool operator!=(const Coordinate& value) const;
};
It is causing me -Woverloaded-virtual warning on gcc compiler.
I understand this warning due to that function declaration in Point2I hides virtual functions from ISerializable.
But I am not sure if just missing const in Point2I can cause this warning.
Can you please help me understand if it is const which is causing this warning or something else? Warning description from gcc didn't mention anything specifically.
Update:
I found another class Coordinate in my code base which was already overriding this and gcc not throwing warning for this. Only difference in Point2I and Coordinate is I didn't declare it virtual with const in Point2I. It appears just const is hiding base class declaration.
if it is const which is causing this warning or something else?
I'd say that it's something else, namely that you are not actually overriding the base class methods, even if you add const.
The argument const ISerializable* is not the same as const Point2I&.
One solution could be to override the base class methods, using const ISerializable& as the argument, and cast in the overridden methods:
class ISerializable {
public:
// add virtual destructor if you need to delete objects through
// base class pointers later:
virtual ~ISerializable() = default;
virtual bool operator==(const ISerializable&) const { return false; }
virtual bool operator!=(const ISerializable&) const { return true; }
};
class Point2I : public ISerializable {
public:
bool operator==(const ISerializable& value) const override {
auto rhs = dynamic_cast<const Point2I*>(&value);
// rhs will be nullptr if the cast above fails
return rhs && (x == rhs->x && y == rhs->y);
}
bool operator!=(const ISerializable& value) const override {
return !(*this == value);
}
private:
int x = 0;
int y = 0;
};
Example usage:
#include <iostream>
class Foo : public ISerializable { // another ISerializable
public:
};
int main() {
Point2I a, b;
std::cout << (a == b) << '\n'; // true - using Point2I::operator==
Foo f;
std::cout << (a == f) << '\n'; // false - using Point2I::operator==
std::cout << (f == a) << '\n'; // false - using ISerializable::operator==
// this makes the default implementation in ISerializable utterly confusing:
std::cout << (f == f) << '\n'; // false - using ISerializable::operator==
}
Another possible solution could be using CRTP but this would not work if you want to compare different types derived from ISerializable<T>:
template<class T>
class ISerializable {
public:
virtual ~ISerializable() = default;
virtual bool operator==(const T&) const = 0;
virtual bool operator!=(const T&) const = 0;
};
class Point2I : public ISerializable<Point2I> {
public:
bool operator==(const Point2I& value) const override {
return (x == value.x && y == value.y);
}
bool operator!=(const Point2I& value) const override {
return !(*this == value);
}
public:
int x;
int y;
};
There are two problems.
The first one is different types of parameters
In these functions the parameters have the pointer type const ISerializable*
virtual bool operator==(const ISerializable* /*value*/) const { return false;};
virtual bool operator!=(const ISerializable* /*value*/) const { return true;};
and in these functions the parameters have the referenced type const Point2I&
bool operator==(const Point2I& value)
{
return (x == value.x && y == value.y);
}
bool operator!=(const Point2I& value)
{
return !(*this == value);
}
The second one is that the first functions are constant member functions while the second functions are not constant member functions.

How to call function with T& when i have both T& and T as return type of functions with same name

I have a class with two functions named Select and return type of T and T&. i need to call function with T& but it always call function with return type T.
How can i force it to call function with T& as return type.
Here is two functions
template <class T>
T Array2D<T>::Select(const int& row, const int& column) const
{
if ((row*this->columns_) + column < 0 || (row*this->columns_) + column >= this->storage_.Length())
{
AdtException exception("Index Out of Bound");
throw exception;
}
return this->storage_[(row*this->columns_) + column];
}
template <class T>
T& Array2D<T>::Select(const int& row, const int& column)
{
if ((row*this->columns_) + column < 0 || (row*this->columns_) + column >= this->storage_.Length())
{
AdtException exception("Index Out of Bound");
throw exception;
}
return (this->storage_[(row*this->columns_) + column]);
}
Here is calling code.
template <class T>
T& Row<T>::operator[](const int& column)
{
T t = this->arr_.Select(row_, column);
T& t1 = t;
return t1;
}
template <class T>
T Row<T>::operator[](const int& column) const
{
return this->arr_.Select(row_, column);
}
Here are the interfaces
class IRow
{
public:
virtual ~IRow() = default;
virtual T& operator[](const int& column) = 0;
virtual T operator[](const int& column) const = 0;
};
class IArray2D
{
public:
virtual ~IArray2D() = default;
virtual T Select(const int& row, const int& column) const noexcept(false) = 0;
virtual T& Select(const int& row, const int& column) noexcept(false) = 0;
virtual Row<T> operator[](const int& row) const noexcept(false) = 0;
virtual Row<T> operator[](const int& row) noexcept(false) = 0;
virtual explicit operator bool() const noexcept = 0;
virtual size_t Rows() const noexcept = 0;
virtual size_t Columns() const noexcept = 0;
virtual void Rows(const size_t& rows) noexcept(false) = 0;
virtual void Columns(const size_t& columns) noexcept(false) = 0;
};
Generally methods can't be overloaded based on the return type because there is no way for a caller to specify which overload he wants. In your case, however, the methods are overloaded using qualifiers: one const another isn't. Which means that in order to call the const version you need to call the method on the const object and opposite goes for the non-const version. For example:
// this will call the T Select(...) const because the array is const
static_cast<const Array2D<T> &>(_arr).Select(_row, column);

Overriding template function in specialized daughter class

I have a templated class MatchBase with a function for the operator == as such
template<typename Element>
class MatchBase{
virtual bool operator ==(const MatchBase<Element>& m) const{
if(_v1 == m.getFirst() && _v2 == m.getSecond()){
return true;
}
return false;
}
I know have a daughter class Match that is template specialized. The class Place used for the specialization does not have an operator== to do the comparison. Thus I'm trying to override the operator== to work with the class Place.
On the things I have tried :
class Match : public betterGraph::MatchBase<graphmatch::Place>{
public :
Match(const graphmatch::Place& v, const graphmatch::Place& vv) :
betterGraph::MatchBase<graphmatch::Place>(v, vv)
{};
virtual bool operator ==(const Match& m) const{
if(_v1.mass_center == m.getFirst().mass_center && _v2.mass_center == m.getSecond().mass_center){
return true;
}
return false;
}
};
I also tried
virtual bool operator ==(const betterGraph::MatchBase<graphmatch::Place>& m) const{
if(_v1.mass_center == m.getFirst().mass_center && _v2.mass_center == m.getSecond().mass_center){
return true;
}
return false;
}
But I always hit an error of the type :
error: no match for ‘operator==’ (operand types are ‘const AASS::graphmatch::Place’ and ‘const AASS::graphmatch::Place’)
if(_v1 == m.getFirst() && _v2 == m.getSecond()){
Because it tries to compile the method from the Base class.
Is there any way for me to override this function of the base class in the daughter class ? I've read the question here but here it's the method that is specialized while my class is specialized so I don't see how to do a forward declaration :/.
The function may be virtual but it's still initialized when you inherit your base class.
This is essential as you might write something like this:
MatchBase<Place> test = Match(p1,p2);
MatchBase<Place> is the base class of Match yet they are not the same.
Calling MatchBase<Place>::operator==() will still call the function defined in your template base class.
You have now multiple option:
- make the function in the base class a pure virtual
- implement Place::operator==()
- pass a comperator as argument to your base class as argument
The first two should be clear (if not please ask). For the third this might be a one possible way to do it:
template<typename Element, typename Less = std::less<Element>>
class MatchBase {
protected:
Element _v1;
Element _v2;
public:
MatchBase(const Element& v, const Element& vv) : _v1(v), _v2(vv)
{}
virtual bool operator ==(const MatchBase<Element, Less>& m) const {
Less less;
bool v1Equal = !less(_v1, m.getFirst()) && !less(m.getFirst(), _v1);
bool v2Equal = !less(_v2, m.getSecond()) && !less(m.getSecond(), _v2);
return v1Equal && v2Equal;
}
const Element& getFirst() const { return _v1; }
const Element& getSecond() const { return _v2; }
};
struct Place
{
int mass_center;
};
struct PlaceLess
{
bool operator()(const Place& p1, const Place& p2)
{
return p1.mass_center < p2.mass_center;
};
};
class Match : public MatchBase <Place, PlaceLess>
{
public:
Match(const Place& v, const Place& vv) :
MatchBase<Place, PlaceLess>(v, vv)
{};
};
Another way might be to specialize std::less<T> in this context. So you won't need to pass it as template parameter.
template<typename Element>
class MatchBase {
protected:
Element _v1;
Element _v2;
public:
MatchBase(const Element& v, const Element& vv) : _v1(v), _v2(vv)
{}
virtual bool operator ==(const MatchBase<Element>& m) const {
std::less<Element> less;
bool v1Equal = !less(_v1, m.getFirst()) && !less(m.getFirst(), _v1);
bool v2Equal = !less(_v2, m.getSecond()) && !less(m.getSecond(), _v2);
return v1Equal && v2Equal;
}
const Element& getFirst() const { return _v1; }
const Element& getSecond() const { return _v2; }
};
struct Place
{
int mass_center;
};
template<>
struct std::less<Place>
{
bool operator()(const Place& p1, const Place& p2)
{
return p1.mass_center < p2.mass_center;
};
};
class Match : public MatchBase <Place>
{
public:
Match(const Place& v, const Place& vv) :
MatchBase<Place>(v, vv)
{};
};
Of course you could merge these ways so you might override the Less template parameter if needed.
If you don't plan on using predefined types (thinking of int, std::string, etc...) you could also make sure that the class passed as Element must inherit a class/struct that enforces that operator== is implemented:
template <typename T>
struct IComparable
{
virtual bool operator==(const T& other) const = 0;
};
template<typename Element>
class MatchBase {
static_assert(std::is_base_of<IComparable<Element>, Element>::value, "Element must implement comparable");
protected:
Element _v1;
Element _v2;
public:
MatchBase(const Element& v, const Element& vv) : _v1(v), _v2(vv)
{}
virtual bool operator ==(const MatchBase<Element>& m) const {
return _v1 == m._v1 && _v2 == m._v2;
}
};
struct Place : public IComparable<Place>
{
int mass_center;
bool operator==(const Place& other) const
{
return mass_center == other.mass_center;
};
};
class Match : public MatchBase <Place>
{
public:
Match(const Place& v, const Place& vv) :
MatchBase<Place>(v, vv)
{};
};

Iterator Implementation - (Linked List Queue)

I am implementing an iterator for a Queue data type, but the iterator is being initialized as a const inside of the class implementation for some reason. I cannot figure out why the constructor is causing the iterator to return itself as a const.
Any feedback as to what the intricasies of the C++ language that may be causing my problem could be, would be very helpful.
The Error I am receiving from Eclipse which seems to be coming from my begin() method is:
../src/linked_queue.hpp:315:35: error: invalid conversion from
'const ics::LinkedQueue<int>*' to 'ics::LinkedQueue<int>*' [-fpermissive]
Interface:
#ifndef LINKED_QUEUE_HPP_
#define LINKED_QUEUE_HPP_
#include <string>
#include <iostream>
#include <sstream>
#include <initializer_list>
#include "ics_exceptions.hpp"
namespace ics {
template<class T> class LinkedQueue {
public:
//Destructor/Constructors
~LinkedQueue();
LinkedQueue ();
LinkedQueue (const LinkedQueue<T>& to_copy);
explicit LinkedQueue (const std::initializer_list<T>& il);
template <class Iterable>
explicit LinkedQueue (const Iterable& i);
//Queries
bool empty () const;
int size () const;
T& peek () const;
std::string str () const; //supplies useful debugging information; contrast to operator <<
//Commands
int enqueue (const T& element);
T dequeue ();
void clear ();
template <class Iterable>
int enqueue_all (const Iterable& i);
//Operators
LinkedQueue<T>& operator = (const LinkedQueue<T>& rhs);
bool operator == (const LinkedQueue<T>& rhs) const;
bool operator != (const LinkedQueue<T>& rhs) const;
template<class T2>
friend std::ostream& operator << (std::ostream& outs, const LinkedQueue<T2>& q);
private:
class LN;
public:
class Iterator {
public:
~Iterator();
T erase();
std::string str () const;
LinkedQueue<T>::Iterator& operator ++ ();
LinkedQueue<T>::Iterator operator ++ (int);
bool operator == (const LinkedQueue<T>::Iterator& rhs) const;
bool operator != (const LinkedQueue<T>::Iterator& rhs) const;
T& operator * () const;
T* operator -> () const;
friend std::ostream& operator << (std::ostream& outs, const LinkedQueue<T>::Iterator& i) {
outs << i.str();
return outs;
}
friend Iterator LinkedQueue<T>::begin () const;
friend Iterator LinkedQueue<T>::end () const;
private:
LN* prev = nullptr;
LN* current;
LinkedQueue<T>* ref_queue;
int expected_mod_count;
bool can_erase = true;
Iterator(LinkedQueue<T>* iterate_over, LN* initial);
};
Iterator begin () const;
Iterator end () const;
private:
class LN {
public:
LN () {}
LN (const LN& ln) : value(ln.value), next(ln.next){}
LN (T v, LN* n = nullptr) : value(v), next(n){}
T value;
LN* next = nullptr;
};
LN* front = nullptr;
LN* rear = nullptr;
int used = 0; //Cache for number of values in linked list
int mod_count = 0; //For sensing any concurrent modifications
//Helper methods
void delete_list(LN*& front);
};
Implementation (I've included only a section of my Iterator code):
template<class T>
auto LinkedQueue<T>::begin () const -> LinkedQueue<T>::Iterator {
return Iterator(this, this->front);
}
template<class T>
auto LinkedQueue<T>::end () const -> LinkedQueue<T>::Iterator {
// return Iterator(this, this->rear);
}
template<class T>
LinkedQueue<T>::Iterator::Iterator(LinkedQueue<T>* iterate_over, LN* initial) {
ref_queue = iterate_over;
expected_mod_count = iterate_over->mod_count;
current = initial;
}
The error is because Iterator begin () const; is marked as const, hence the this used in the function is const as well. So in turn, the compiler gives the error that it cannot convert from a const to non-const.
Given that the function signatures are fixed in this case, to resolve the error, added const will help solve the issue.
You could add const to the constructor signature
Iterator(LinkedQueue<T> const* iterate_over, LN* initial);
And make the member const as well
LinkedQueue<T> const* ref_queue;
Adding the const where required to ensure that members and functions remain const as required is known as being const correct.