Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Hi I'm tring to create something like wrapper class for primitive types but I'm stuck on this issue:
When I try to create interface and be able to use polymorphism with descendants
edit
I'm getting
function returning abstract class "Var" is not allowed:
function "Var::operator+" is a pure virtual
function function "Var::operator-" is a pure virtual function
function "Var::operator*" is a pure virtual function
function "Var::operator/" is a pure virtual function
Here is my code
class Var
{
public:
Var() { }
virtual Var operator+(Var b) = 0;
virtual Var operator-(Var b) = 0;
virtual Var operator*(Var b) = 0;
virtual Var operator/(Var b) = 0;
};
class Decimal : public Var
{
public:
Decimal(double a) { value = a; }
Decimal() : Decimal(0) { };
virtual Decimal operator+( Decimal b)
{
return value + b.value;
}
virtual Decimal operator-( Decimal b)
{
return value - b.value;
}
virtual Decimal operator*( Decimal b)
{
return value * b.value;
}
virtual Decimal operator/( Decimal b)
{
return value / b.value;
}
Decimal operator=(double val)
{
value = val;
}
private:
double value;
};
any solution to my problem?
I think you are going about this the wrong way. Try a template
template<class T>
class Var
{
public:
typedef T Type;
Var(const Type& value = Type()) : value(value) {}
friend Var operator+(const Var& left, const Var& right)
{
return Var(left.value + right.value);
}
private:
Type value;
};
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I tried to override the - operator but I get an error. How to solve the error, and what is it for?
#pragma once
class Resurse
{
protected:
unsigned int _cantitate;
public:
Resurse() {}
Resurse(unsigned int cantitate) :_cantitate(cantitate) {}
~Resurse() {}
Resurse(Resurse&& r)
{
_cantitate = r._cantitate;
r._cantitate = 0;
}
virtual Resurse* operator-(Resurse* r)
{
Resurse* result=new Resurse(this->_cantitate - r->_cantitate);
return result;
}
unsigned int GetCantitate() { return _cantitate; }
};
#pragma once
#include "Resurse.h"
class Hrana:public Resurse
{
public:
Hrana() {}
Hrana(unsigned int cantitate) :Resurse(cantitate) {}
~Hrana() {}
Hrana(Hrana&& h) { _cantitate = h._cantitate; h._cantitate = 0; }
Resurse* operator-(Resurse* r)
{
Resurse* result = new Hrana(this->_cantitate - r->GetCantitate());
return result;
}
};
void main()
{
Resurse* hrana1 = new Hrana(20);
Resurse* hrana2 = new Hrana(17);
Resurse* result = hrana1 - hrana2;
system("pause");
}
Yes, it is possible to overload (not override) operators. However, the problem is, you are not doing it correctly.
You are trying to invoke operator- on Resurce* pointers, not on Resurce objects. Your operator- needs to take a Resurce object by value/reference as input, not by pointer. And return a new Resurce object by value on output, not by pointer. See What are the basic rules and idioms for operator overloading?
And in your main(), you need to dereference the pointers before calling operator-.
Try this:
Resurse operator-(const Resurse &r) const
{
return Resurse(_cantitate - r._cantitate);
}
int main()
{
Resurse* hrana1 = new Resurse(20);
Resurse* hrana2 = new Resurse(17);
Resurse result = *hrana1 - *hrana2;
std::system("pause");
delete hrana2;
delete hrana1;
}
Or, simply get rid of the pointers altogether, you don't really need them:
int main()
{
Resurse hrana1(20);
Resurse hrana2(17);
Resurse result = hrana1 - hrana2;
std::system("pause");
}
UPDATE: I just realized that you are trying to implement a polymorphic operator-. That is not going to work, mainly due to object slicing on the return value, but also because you can't overload operators for pointers.
I would suggest using a separate virtual method instead of operator-, eg:
#pragma once
#include <memory>
class Resurse
{
protected:
unsigned int _cantitate;
public:
Resurse(unsigned int cantitate = 0) : _cantitate(cantitate) {}
virtual ~Resurse() {}
Resurse(const Resurse&) = default;
Resurse(Resurse&& r)
{
_cantitate = r._cantitate;
r._cantitate = 0;
}
virtual std::unique_ptr<Resurse> subtract(const Resurse &r) const
{
return std::make_unique<Resurse>(_cantitate - r.GetCantitate());
}
unsigned int GetCantitate() const { return _cantitate; }
};
#pragma once
#include "Resurse.h"
#include <memory>
#include <cstdlib>
class Hrana : public Resurse
{
public:
Hrana(unsigned int cantitate = 0) : Resurse(cantitate) {}
Hrana(const Hrana& h) = default;
Hrana(Hrana&& h) : Resurse(std::move(h)) {}
std::unique_ptr<Resurse> subtract(const Resurse &r) const override
{
return std::make_unique<Hrana>(_cantitate - r.GetCantitate());
}
};
void main()
{
std::unique_ptr<Resurse> hrana1 = std::make_unique<Hrana>(20);
std::unique_ptr<Resurse> hrana2 = std::make_unique<Hrana>(17);
auto result = hrana1->subtract(*hrana2);
std::system("pause");
}
Say I have class galaxy. A sensible variable to include in this class would be double mass. Practically, this is an example of a variable that would have inherent restrictions, especially if considering the galaxies we know of today.
What I want to know is: how would you encode this restriction in the class? I would want an error when trying to create galaxy Andromeda(unfeasible mass) for example.
You can obviously do error checks on inputs if you're taking in data, but is there a way to make this inherent in the class?
You can simplify input checking, with a simple wrapper class, to make the check easier
template<typename T, T MinRange_, T MaxRange_>
struct RangeRestrictedValue {
T value;
RangeRestrictedValue(const char* paramName_ = nullptr)
: value(doRangeCheck(T())), paramName(paramName_) {}
RangeRestrictedValue(const T& value_, const char* paramName_ = nullptr)
: value(doRangeCheck(value_)), paramName(paramName_) {}
RangeRestrictedValue& operator=(const T& value_) {
value = doRangeCheck(value_);
return *this;
}
static T& doRangeCheck(const T& value) {
std::ostringstream message;
message << (paramName ? paramName : "value") << " is out of range.";
if(value < MinRange_ || value > MaxRange_) {
throw std::out_of_range(message.str().c_str());
}
}
const char* paramName;
};
And use that like
class Galaxy {
private:
typedef RangeRestrictedValue<double,MIN_GALAXY_MASS,MAX_GALAXY_MASS> GalaxyMass;
GalaxyMass mass;
public:
Galaxy(double mass_) : mass(mass_,"mass") {}
double mass() const { return mass.value; }
void mass(double mass_) { mass = mass_; }
void doSomething() {
// access mass.value as you need to
}
};
We cannot make operator++(int) virtual directly because of the return type problem. The usual advice is to apply the curiously named Curiously Recurring Template Pattern, which I implemented to the best of my modest understanding as follows:
// abstract numeric type
template <typename T>
class A {
public:
virtual T& operator++() = 0;
virtual T get() const = 0;
virtual string toString() const = 0;
virtual T operator++(int) {
T old(this->get());
++*this; // calls operator++() from derived class
return old;
}
friend ostream& operator<<(ostream& os, const A& a) {
return os << a.toString();
}
virtual ~A() = 0;
};
// signed numeric type
class S : public A<S> {
public:
S(long l) : m_l(l) {}
virtual S get() const { return m_l; }
virtual string toString() const { return to_string(m_l); }
virtual S& operator++() { // no wrapping, caps at LONG_MAX
if (m_l < LONG_MAX)
++m_l;
return *this;
}
private:
long m_l;
};
// unsigned numeric type
class U : public A<U> {
public:
U(unsigned long ul) : m_ul(ul) {}
virtual U get() const { return m_ul; }
virtual string toString() const { return to_string(m_ul); }
virtual U& operator++() { // no wrapping, caps at ULONG_MAX
if (m_ul < ULONG_MAX)
++m_ul;
return *this;
}
private:
unsigned long m_ul;
};
Lots of code duplication, but at least it allows for constructs like the following to run, which is definitely a start:
template <typename T>
void pinc(A<T>& a) {
cout << a++ << ' ' << a << endl;
}
int main() {
S s(LONG_MAX);
pinc(s);
U u(LONG_MAX);
pinc(u);
return 0;
}
Sadly, it does not help with things like vector<A*>: S and U have no common ancestor. If I derive A from another base class, I also have to move the templated part there and the problem - ha! - goes recursive.
So, any suggestions?
Note to editors: Having learned my lesson, I saved the original this time. :)
I do not think this is possible within C++ type system, here is why:
Consider the following example: Let say we somehow achieve this and have A* a pointer to the base class from which U and S was derived. Then what will be the type of the var = (*a)++;? It could be either U or S depending on what a is pointing to. But compiler need to know return type during compilation because operator++(int) return S and U by-value.
I see the following ways to work around this problem but they all need to change the return types of operator++(int) in hierarchy to make them covariant (see C++ virtual function return type):
Return pointer to a (base) class within your hierarchy
If your types is integer types (like operator++ return char, int, long for different classes) then you can make them all return enclosing type: long int
Instead of returning direct values of your objects (U or S) return some kind of struct that is capable of holding any of these types. (see http://www.boost.org/doc/libs/1_61_0/doc/html/any.html for possible generic way to do this)
I am just starting with C++. I am trying to design a class(interface) for a subset of vector operations. This Abstract Base Class is defined as:
//file: vect.hh
#ifndef _vect_hh
#define _vect_hh
class vect
{
public:
virtual double norm() const = 0;
virtual void add(const double scaleThis, const double scaleOther,
const vect& other) = 0;
virtual double dot(const vect& other) const = 0;
virtual vect* clone() const = 0;
virtual vect* copy(const vect& other) const = 0;
virtual ~vect()=default;
};
#endif
The problems appears in the functions that has as argument const vect& other. Since in the derived class what I really want is something like
const vectDerived& other as argument. To exemplify the problem I made a simple implementation of the previous class using raw pointers. Because I have some others problems that I going to comment at the end of this question I have inserted the full definition of the class. But keep in mind the most important functions are dot and add:
// file: vectDouble.hh
#ifndef _vectDouble_hh
#define _vectDouble_hh
#include <cmath>
#include <cstring>
#include "vect.hh"
class vectDouble: public vect
{
public:
explicit vectDouble(const int n): n{n}, elem{new double[n]}
{
std::memset(elem,'\0',sizeof(double)*n);
}
~vectDouble() override {delete[] elem;}
vectDouble(const vectDouble& other): n{other.n}, elem{new double[n]}
{
std::memcpy(elem, other.elem, n*sizeof(double));
}
vectDouble& operator=(const vectDouble& other)
{
if(&other != this){
delete[] elem; n = other.n;
elem = new double[n];
std::memcpy(elem, other.elem, sizeof(double)*n);
}
return *this;
}
vectDouble(vectDouble&& other): n{0}, elem{nullptr}
{
fillClass(other, *this);
}
vectDouble &operator=(vectDouble&& other)
{
if(&other != this){
delete[] elem;
fillClass(other, *this);
other.elem = nullptr; other.n = 0;
}
return *this;
}
double norm() const override
{
double norm = 0.0;
for(int i=0;i<n;i++){norm += elem[i]*elem[i];}
return std::sqrt(norm);
}
double dot(const vect& other) const override
{
const vectDouble &v = dynamic_cast<const vectDouble&>(other);
double dot = 0.0;
for(int i=0;i<n;i++){dot += elem[i]*v.elem[i];}
return dot;
}
void add (const double scaleThis, const double scaleOther,
const vect& other) override
{
const vectDouble &v = dynamic_cast<const vectDouble&>(other);
for(int i=0;i<n;i++){
elem[i] = scaleThis*elem[i] + scaleOther*v.elem[i];
}
}
double& operator[](const int i){return elem[i];}
const double& operator[](const int i) const {return elem[i];}
int size() const{return n;}
vectDouble* clone() const override
{
return new vectDouble(*this);
}
vectDouble* copy(const vect& other) const override
{
const vectDouble &v = dynamic_cast<const vectDouble&>(other);
auto *t = new vectDouble(*this);
t->n = v.n;
std::memcpy(t->elem, v.elem, t->n*sizeof(double));
return t;
}
private:
void fillClass(const vectDouble& in, vectDouble& out)
{
out.n = in.n; out.elem = in.elem;
}
int n;
double *elem;
};
#endif
In both functions I used const vectDouble &v = dynamic_cast<const vectDouble&>(other); to convert the base class reference to a reference with type of the derived class. This is a valid use case for the dynamic_cast. If not, what is the proper way to achieve this result?
I have remarked that I have run in other problems (sorry for straying away of the main question). As example of use of the abstract class and of the previous implementation I made this simple and somewhat contrived main program:
// file main.cc
#include <iostream>
#include <memory>
#include "vectDouble.hh"
double lsfit(const vect& dobs, const vect& dcalc)
{
std::unique_ptr<vect> tmp(dcalc.copy(dcalc));
return (dobs.dot(dcalc))/(dcalc.dot(*tmp));
}
void testFit()
{
vectDouble d{10};
vectDouble x{10};
for(int i=0;i<x.size();i++){
d[i] = static_cast<double>(3*i);
x[i] = static_cast<double>(i);
}
std::cout<<"alpha="<<lsfit(d, x)<<std::endl;
}
int main()
{
testFit();
return 0;
}
This program illustrate one use case envisioned for the interface described. However without the use of the std::unique_ptr there is a memory leak (identified using the option -fsanitize=leak from the g++compiler). If Instead of using the unique_ptr I wanted to manually manage the memory (as curiosity) what is the proper way to clean up this result? Is possible to return directly a std::unique_ptr from the copy function. When I tried to do this I received error messages relative to wrong covariant return types.
Remarks:
1) The intent of this interface is to abstract the storage scheme used to represent the arrays, for instance a file instead of an in memory representation.
2) I am aware that the copy function presented is more akin to create/clone plus copy function.
3) The structure presented is adequated if in the future I wanted to use templates in both the base and derived classes? For instance template<float> class vect{...} and template <float> class vectDerived{...}?
Following the advice of #hayt I have changed the definitions of both vect.hh and vectDouble.hh to use the CRTP pattern described. After these changes I also changed the definition of the function lsftit to:
template <class Derived> double lsfit2(const Derived& dobs, const Derived& dcalc)
{
std::unique_ptr<Derived> tmp = dcalc.clone();
Derived *t = tmp.get();
t->copy(dcalc);
return (dobs.dot(dcalc))/(dcalc.dot(*t));
}
Is this a proper way to define this function when using this pattern?
Thanks.
You should check if you really need inheritance and maybe switch to one generic vector class with a template parameter (from you only have "double" as something specific)
An alternative would be using CRTP in combination with declaring an interface. (I also added the unique_ptr in this apporach)
template <class Derived>
class vect
{
public:
virtual double norm() const = 0;
virtual void add(const double scaleThis, const double scaleOther,
const Derived& other) = 0;
virtual double dot(const Derived& other) const = 0;
virtual std::unique_ptr<Derived> clone() const = 0;
virtual std::unique_ptr<Derived> copy(const vect& other) const = 0;
virtual ~vect()=default;
};
This way you have the same "interface" but a different "base class" and you have the derived class also in your functions here. So you will not have to worry about assigning "incompatible" vectors to each other via the interfaces (see dynamic_cast).
Additionally you can later derive the class for further specifications.
Here is what you class would look like with this approach:
class vectDouble: public vect<vectDouble>
{
public:
//...
//NOTE: here vecDouble is a parameter. no need for dynamic casts
double dot(const vectDouble& other) const override
{
double dot = 0.0;
for(int i=0;i<n;i++){dot += elem[i]*other.elem[i];}
return dot;
}
void add (const double scaleThis, const double scaleOther,
const vectDouble& other) override
{
for(int i=0;i<n;i++){
elem[i] = scaleThis*elem[i] + scaleOther*other.elem[i];
}
}
//also directly a unique pointer
std::unique_ptr<vectDouble> clone() const override
{
return std::make_unique<vectDouble>(*this);
}
//...
};
This question already has answers here:
C++ Memoization understanding
(3 answers)
Writing Universal memoization function in C++11
(5 answers)
Closed 8 years ago.
Consider the following code (compiles with gcc 4.7.2):
#include<iostream>
#include<memory>
struct Base
{
~Base() {}
virtual double operator()(double x) const = 0;
};
template<typename F, typename G> struct Compose;
struct A : public Base
{
virtual double operator()(double x) const {return x;} //suppose this is a hard-to.calculate function, lots of temporaries, maybe also time-dependent, etc
template <typename F>
Compose<A,F> operator()(const F& f) const {return Compose<A,F>(*this,f);}
};
struct B : public Base
{
virtual double operator()(double x) const {return x*x;} //suppose this is a hard-to.calculate function, lots of temporaries, maybe also time-dependent, etc
template <typename F>
Compose<B,F> operator()(const F& f) const {return Compose<B,F>(*this,f);}
};
struct C : public Base
{
virtual double operator()(double x) const {return x*x*x;} //suppose this is a hard-to.calculate function, lots of temporaries, maybe also time-dependent, etc.
template <typename F>
Compose<C,F> operator()(const F& f) const {return Compose<C,F>(*this,f);}
};
template<typename F, typename G>
struct Compose : public Base
{
Compose(const F &_f, const G &_g) : f(_f), g(_g) {}
F f;
G g;
virtual double operator()(double x) const {return f(g(x));}
};
int main()
{
double x=2.0;
A a;
B b;
C c;
std::shared_ptr<Base> ptrBase = std::make_shared<A>(A());
std::shared_ptr<A> ptrA = std::make_shared<A>(a);
std::cout<< a(x) <<std::endl;
std::cout<< ptrBase->operator()(x) <<std::endl;
std::cout<< ptrA->operator()(x) <<std::endl;
std::cout<< b(a(x)) <<std::endl;
std::cout<< c(b(a(x))) <<std::endl;
std::cout<< a(c(b(a(x)))) <<std::endl;
std::cout<< ptrA->operator()(c(b(ptrBase->operator()(x)))) <<std::endl;
}
Output:
2
2
2
4
64
64
64
Ok, long prelude for a short question. Several redundant calculations occur here, for instance, the result of A()(x) is calculated six times (some via objects, some via pointers). How can I implement a global output array which stores the evaluated function values?
One approach which came to my mind and should work is to implement a function std::string id() unique to each (composed) class, plus a global std::map<std::string,double> to store the results, and then check whether a (current) result exists.
Do you see other and maybe better approaches here? Thanks in advance.
Sorry guys, although there are some similarities (the word "memoization" which seems to somehow trigger a reflex), I really don't see why this should be duplicate ... but I'm open to discussion.
The case above is in my opinion much more complex than those in the linked threads (e.g., its not simply a fibonacci-function). Moreover, as far I can see the highlighted memoization class will treat objects and pointers differently (at least without further editing). My intention was to arrive at a pattern in which each result is calculated only once, regardles how it is invoked.
Up to now, I was playing around with CRTP'ed static results classes, which leads to the following code (compiles with gcc 4.7.2.):
#include<iostream>
#include<memory>
#include<string>
#include<map>
struct Base
{
virtual ~Base() {}
virtual double operator()(double x) const = 0;
virtual std::string id() const = 0;
};
template<typename F, typename G> struct Compose;
template<typename T>
struct Result
{
virtual ~Result() {}
double get(double x) const
{
return mem.find(x)->second;
}
bool isSet(double x) const {it=mem.find(x); return it!=mem.end();}
//get the previously found result by isSet(x)
double get() const
{
return it->second;
}
protected:
//the set function is const, as it works only on static variables
//don't know whether it is the best idea, but it allows for a const operator() later...
void set(double x, double y) const
{
mem.insert(std::make_pair(x,y));
}
private:
static std::map<double, double> mem;
static std::map<double, double>::const_iterator it;
};
template<typename T> std::map<double, double> Result<T>::mem;
template<typename T> std::map<double, double>::const_iterator Result<T>::it=Result<T>::mem.begin();
struct A : public Base, public Result<A>
{
virtual double operator()(double x) const
{
if(isSet(x))
{
return get();
}
else
{
double y=x;
set(x,y);
std::cout<<"setA ";
return y;
}
}
template <typename F>
Compose<A,F> operator()(const F& f) const {return Compose<A,F>(*this,f);}
virtual std::string id() const {return "A";}
};
struct B : public Base, public Result<B>
{
virtual double operator()(double x) const
{
if(isSet(x))
{
return get();
}
else
{
double y=x*x;
set(x,y);
std::cout<<"setB ";
return y;
}
}
template <typename F>
Compose<B,F> operator()(const F& f) const {return Compose<B,F>(*this,f);}
virtual std::string id() const {return "B";}
};
struct C : public Base, public Result<C>
{
virtual double operator()(double x) const
{
if(isSet(x))
{
return get();
}
else
{
double y=x*x*x;
set(x,y);
std::cout<<"setC ";
return y;
}
}
template <typename F>
Compose<C,F> operator()(const F& f) const {return Compose<C,F>(*this,f);}
virtual std::string id() const {return "C";}
};
template<typename F, typename G>
struct Compose : public Base, public Result<Compose<F,G> >
{
Compose(const F &_f, const G &_g) : f(_f), g(_g) {}
F f;
G g;
virtual double operator()(double x) const
{
if(this->isSet(x))
{
return this->get();
}
else
{
double y=f(g(x));
this->set(x,y);
std::cout<<"set"<<this->id()<<" ";
return y;
}
}
virtual std::string id() const {return f.id() + "(" + g.id() + ")";}
};
int main()
{
double x=2.0;
A a;
B b;
C c;
std::shared_ptr<Base> ptrBase = std::make_shared<A>(A());
std::shared_ptr<A> ptrA = std::make_shared<A>(A());
std::cout<<"-------------------------------"<<std::endl;
std::cout<< a(x) <<std::endl;
std::cout<<ptrBase->operator()(x) <<std::endl;
std::cout<<ptrA->operator()(x) <<std::endl;
std::cout<<"-------------------------------"<<std::endl;
std::cout<<c(x)<<std::endl;
std::cout<<C()(x)<<std::endl;
std::cout<<C()(x)<<std::endl;
std::cout<<"-------------------------------"<<std::endl;
auto ba= b(a);
std::cout<<ba(x) << std::endl;
auto cba= c(ba);
std::cout<<cba(x)<< std::endl;
auto acba= a(cba);
std::cout<<acba(x)<<std::endl;
}
Output:
-------------------------------
setA 2
2
2
-------------------------------
setC 8
8
8
-------------------------------
setB setB(A) 4
setC(B(A)) 64
setA(C(B(A))) 64
-------------------------------
Ok, some things to note here:
By inheritance from the static results class, it is interesting how all the differently called A's (by object, by pointer-to-object, by pointer-to-base) retrieve the stored result (there is only one set). Same for C() which is called three times but set only once.
In order to anticipate the next reflex, I know that multiple inheritance can be bad, but the classes seem to be well separated. The same behavior is probably obtained by composition, so please forget about that point.
In fact, this isn't really a memoization class yet, as it simply stores the result which was calculated first. Thus it also gives wrong results [eg. for C(B(A))]. However, this can be easily cured by a map or whatever. I will do this later eventually, at the moment its only about the pattern (EDIT: is done).
And as a last point, I'm aware that a different solution than in the seemingly-duplicated threads doesn't imply a different questions. Yet, it will maybe (--hopefully) yield some extension of the memoization-topic on this page from which all can benefit.
I'm looking forward to your thoughts. Thanks in advance!
EDIT 2: Helping yourself is a good thing, now the code works as I was looking for. I have updated it in the post above.
Changes:
Added a map to actually make a real memoization class out of it. Caution: double comparison is dangerous, so one should better pass a more approriate comparison function instead of the standard equality.
Made the static members of the results array private, and the setters protected, as only the function-classes may change the results.
Still the map types are not given by template parameters (as in the linked threads). That is overhead which I don't need (and probably YAGNI too).
Now I'll stop talking to myself. Comments are still welcome. Thanks, David