C++ Problem: Class Promotion using derived class - c++

I have a class for Float32 that is derived from Float32_base
class Float32_base {
public:
// Constructors
Float32_base(float x) : value(x) {};
Float32_base(void) : value(0) {};
operator float32(void) {return value;};
Float32_base operator =(float x) {value = x; return *this;};
Float32_base operator +(float x) const { return value + x;};
protected:
float value;
}
class Float32 : public Float32_base {
public:
float Tad() {
return value + .01;
}
}
int main() {
Float32 x, y, z;
x = 1; y = 2;
// WILL NOT COMPILE!
z = (x + y).Tad();
// COMPILES OK
z = ((Float32)(x + y)).Tad();
}
The issue is that the + operator returns a Float32_base and Tad() is not in that class. But 'x' and 'y' are Float32's.
Is there a way that I can get the code in the first line to compile without having to resort to a typecast like I did on the next line?

You can use CRTP if you only need one-level deep inheritance:
template <typename T>
struct A
{
T
operator+ (const A&)
{ return T (); }
};
struct B : A <B>
{
void
lol ()
{ }
};
int
main ()
{
B a, b;
(a + b).lol ();
}

You have to override the operator+ method since your return type for operator+ is defined as Float32_base. You can do this through covariance and make the method virtual. Then override the method in your subclass (you could probably just call the method in the superclass).
You could also do this through Templates, but if you're not familiar with Templates I wouldn't suggest digging into it. Essentially you would define the virtual function the way you already did but instead of returning Float32_base, you would return your template type. (as long as your template type is a subclass then C++ should be good with contravariance). Your subclass would extend the baseclass with a template of the subclass.

You can template the FLoat32_base class on the result type of operations.
Or put everything into a single class (probably best), delegating the few platform-specific operations to platform specific functions.
Cheers & hth.,

Related

A function overload depending on enum

Sorry for the noob question, but I cannot seem to get my head around C++'s static nature. The problem: I have a class that returns an enum and depending on it I have to convert the said class using another class and return a vector. In code:
enum TYPES { TYPE_A, TYPE_B, TYPE C }
class A {
TYPES getType() {}
}
class B : public A {}
class C : public A {}
class D : public A {}
std::vector<?> convert_to_vector(const A& a) {
// depending on what enum is returned by a.getType()
// I have to convert a into B, C, or D class and return std::vector of
// an appropriate type, e.g. int for B, float for C, etc.
}
int main() {
A a;
auto v = convert_to_vector(a);
}
The simplest way would be using switch(a.getType()) but I have different return types in each case and using auto as the return type doesn't work. I have tried templates and template specification, but they don't accept the runtime variable that is return by a.getType(). I guess there must be some simple solution that I'm overlooking here, but I have run out of ideas at this point and would be grateful for any pointers.
Thanks!
You can't change the return type of a C++ function at runtime. But you can use a variant type:
std::variant<std::vector<int>, std::vector<float>> convert_to_vector(const A& a) {
if (a.getType() == TYPE_B)
return std::vector<int>();
if (a.getType() == TYPE_C)
return std::vector<float>();
throw std::logic_error("unsupported type");
}
If you don't have C++17, you can use boost::variant instead of std::variant.
I think instead of deciding the type of a vector on an enum a much better solution would be to have a parent class A which can have a vector inside it which is based on a template variable. In your classes B, C, D you can simply inherit A and specify a template type. So, when you create a new object for B, C, D you will already have a vector member for those objects. You can also have a virtual function convertToVec which you can override in the child classes depending on how you want to convert data into a vector.
template<class T>
class A {
std::vector<T> vec;
std::vector<T> GetVector() { return vec; }
virtual convertToVec() { .... }
}
class B : public A<bool> {}
class C : public A<float> {}
class D : public A<long long int> {}
int main() {
B b;
b.GetVector();
//A* b = new B();
//b->convertToVec();
}
While it's pretty hard to follow what exactly you are trying to achieve here, going to use switch-case is not a good idea, instead you'd better to leverage polymorphism. For example:
class A {
public:
virtual void convertToVector(AuxVectorConverter& aux) = 0;
};
class B {
public:
// Add here specific implementation
virtual void convertToVector(AuxVectorConverter& aux) {
aux.convertToVectorB(this);
}
};
class C {
public:
// Add here specific implementation
virtual void convertToVector(AuxVectorConverter& aux) {
aux.doSomethingC(this);
}
};
// Aux class
class AuxVectorConverter {
public:
convertToVector(A* a) {
a->convertToVector(this);
}
convertToVectorB(B* b) {
// Do code specific for B
}
convertToVectorC(C* c) {
// Do code specific for B
}
}
int main() {
AuxVectorConverter* aux;
A* a = ...; // Initialize here either with instance of B or C
// Now, based on run time aux class will issue appropriate method.
aux.convertToVector(a);
}
You might find more details here
UPDATE (Based on comment)
An alternative approach could be to define a map from TYPES to some abstract class which will align with the patter from above, e.g.:
// Map has to be initialized with proper implementation
// of action according to type
map<Types, AbstracatAction> actions;
// Latter in the code you can do:
aux.convertToVector(actions[a->getType()]);
And action will be defined pretty similar to hierarchy I've showed above, e.g.
class AbstractAction {
public:
virtual void convertToVector(AuxVectorConverter& aux) = 0;
};
class ActionB: public AbstractAction {
public:
virtual void convertToVector(AuxVectorConverter& aux) {
aux.covertToVectorB(this);
}
};

Another issue with specialised pure virtual template function (undefined reference)

As a beginner, I have some problem regarding templates, inheritance and pure virtual functions.
Consider the following, where Probability is an abstract template instantiated as RationalProbability.
Probability.h:
template <class T>
class Probability
{
public:
T value;
//Operator overloading for +
virtual Probability<T>* operator+(const Probability<T>& p);
T getValue() const { return value; }
protected:
Probability(T val) {
value = val;
}
~Probability() {};
};
Probability.cpp : empty
RationalProbability.h:
#include "Probability.h"
class RationalProbability: public Probability<float>
{
public:
RationalProbability(float prob);
virtual ~RationalProbability();
RationalProbability* operator+(const RationalProbability& p);
};
RationalProbability.cpp:
#include "RationalProbability.h"
RationalProbability::RationalProbability(float prob): Probability(prob) {}
RationalProbability::~RationalProbability()
{
}
RationalProbability* RationalProbability::operator+(const RationalProbability& p) {
RationalProbability* rp = new RationalProbability(p.getValue() + this->value);
return rp;
}
I get the following error:
Error:undefined reference to
Probability<float>::operator+(Probability<float> const&)
It is true that there is no function with that exact signature, but RationalProbability implements the template exactly with
RationalProbability: public Probability<float>
If you want a base class to have an abstract function (a virtual function you don't implement) you should say so:
virtual Probability<T>* operator+(const Probability<T>& p) = 0;
The = 0 is what tells the compiler that the member function is an abstract method that must be overridden by sub-classes.
If you don't have that, there must be a definition (implementation) of all virtual functions.
If you look closer at the error message it says that it's Probability<float>::operator+ that is missing, not RationalProbability::operator+.
I also suggest you read and check some canonical operator implementations, especially for the binary arithmetic operators, because you should not return a pointer from the operator+ function. It should return an object by value. Otherwise, how would something like a + b + c work if suddenly the result of one addition was a pointer?

Inherited functions to return Derived class, not Base class

Is it possible in C++ to formulate functions in the Base class that return Base type such that in the Derived class, they return Derived type, without overloading?
Minimal example:
class Base
{
public:
Base(double v)
{
value = v;
}
Base add(Base b)
{
return Base(b.value + this->value);
}
void print()
{
std::cout << value << std::endl;
}
double value;
};
class Derived : public Base
{
public:
Derived(double v) : Base(v)
{
}
void timesTwo()
{
value *= 2.0;
}
};
int main()
{
Derived d1(1), d2(2);
// This doesn't work because the result is of type Base
(d1.add(d2)).timesTwo();
return 0;
}
Motivation
In the actual example, Base represents a linear algebra matrix, and Derived represents a vector. The matrix offers many functions that are all applicable to vectors, such as addition or multiplication by a scalar.
In this case, it would be desirable not having to override all these matrix functions manually to return vectors. I would like to, if possible, express that whatever this type is, the return type should be identical to it.
Example:
class Matrix
{
...
Matrix operator*(double x);
};
class Vector : Matrix
{
...
};
Matrix M;
M = M * 2.0; // works
Vector v;
v = v * 2.0; // does not work, because v * 2.0 returns a Matrix
The effort for overriding e.g. operator*() for all derived classes is increased by the fact that there are derived classes for 3- and 2-dimensional vectors, etc.
I understand that a solution is to define a cast from Matrix to Vector (and to Vector3, Vector2, ...) but this would involve copying all entries (which are, for efficiency, stack arrays).
Is there a more efficient solution? And, if not, would it generally be considered cleaner/better to
duplicate all the relevant code in each derived class, or to
define a cast?
In my current understanding, the conflicting problems are:
Duplicate code makes the solution error-prone and more difficult to refactor.
Reusing existing code requires lots of copy operations every time the "scope" changes between Matrix, Vector, Vector3, ... . Would be inefficient if used in large calculations.
Any suggestion would be most appreciated. Thanks!
Yes, but only with free functions (including most operators).
template<class X, class Y,
std::enable_if_t<std::is_base_of<Base, std::decay_t<X>>{},int> =0,
std::enable_if_t<std::is_base_of<Base, std::decay_t<Y>>{},int> =0
>
friend X& operator+=(X&x, Y&& rhs)
{
x.value += rhs.value;
return x.
}
template<class X, class Y,
std::enable_if_t<std::is_base_of<Base, std::decay_t<X>>{},int> =0,
std::enable_if_t<std::is_base_of<Base, std::decay_t<Y>>{},int> =0
>
friend std::decay_t<X> operator+(X&&x, Y&& rhs) {
auto r=std::forward<X>(x);
r+=std::forward<Y>(rhs);
return r;
}
Now if I did that right,
(d1+d2).timesTwo();
works.
I also implemented + in terms of += because that usually works well.
The fancy enable if exists because koenig lookup with very generic template operators causes strange things to happen when you pass Base and types derived from Base to template types and proceed to use + on the resulting type. By saying "only things derived from Base", the right thing happens.
We need to use a template free friend function so we can get the type of "*this" (as it where) within the template to change our return type. This cannot be done in a template member function.
The enable_if clause does not work well in MSVC, but is best practice in other compilers. For MSVC use class=enable_if instead of enable_if=0. The reason why the =0 is best is out of scope here.
Make class Base abstract and put its methods in separated functions. Also declare pure virtual the methods you need in derived classes:
#include <iostream>
class Base
{
public:
Base(double v) : value(v) {}
double value;
virtual void timesTwo() = 0;
};
class Derived : public Base
{
public:
Derived(double v) : Base(v) {}
void timesTwo()
{
value *= 2.0;
std::cout << "timesTwo " << value << std::endl;
}
};
template <class T>
T add(const T& t1, const T& t2)
{
return T(t1.value + t2.value);
}
int main()
{
Derived d1(1), d2(2);
add(d1, d2).timesTwo();
return 0;
}

can't initialize functor objects when passing derived class in C++

This question stems from a previous question I asked here. I cannot use any external libraries or the C++ 11 spec. Meaning I can't use std::bind, std::function, boost::bind,boost::function etc. I have to write it myself. The issue is the following:
Consider the code:
EDIT
Here is a complete program that exhibits the problem as requested:
#include <map>
#include <iostream>
class Command {
public:
virtual void executeCommand() = 0;
};
class Functor {
public:
virtual Command * operator()()=0;
};
template <class T> class Function : public Functor {
private:
Command * (T::*fptr);
T* obj;
public:
Function(T* obj, Command * (T::*fptr)()):obj(obj),
fptr(fptr) {}
virtual Command * operator()(){
(*obj.*fptr)();
}
};
class Addition:public Command {
public:
virtual void executeCommand(){
int x;
int y;
x + y;
}
};
class CommandFactory {
public:
virtual Addition * createAdditionCommand() = 0;
};
class StackCommandFactory: public CommandFactory {
private:
Addition * add;
public:
StackCommandFactory():add(new Addition()) {}
virtual Addition * createAdditionCommand(){
return add;
}
};
void Foo(CommandFactory & fact) {
Function<CommandFactory> bar(&fact,&CommandFactory::createAdditionCommand);
}
int main() {
StackCommandFactory fact;
Foo(fact);
return 0;
}
The error it gives is "no instance of constructor "Function<T>::Function [with T=CommandFactory] matches the argument list, argument types are: (CommandFactory *, Addition * (CommandFactory::*)())
I think it's complaining because I'm passing it a derived type. I have to use pointers/references to the abstract classes because fact may not be a StackCommandFactory later down the road.
I can't say:
void Foo(CommandFactory & fact){
Function<CommandFactory> spf(&fact,&fact.createAdditionCommand); //error C2276
}
because of then I receive error C2276 which says (as in the question I linked to) '&' : illegal operation on bound member function expression.
So explicitly my question is: "How do I initialize this functor object so that I can use it with the above mentioned interfaces?"
Here's a modification of my original answer that seems to do what you need, without using the any functor stuff from C++11 or boost.
#include <vector>
#include <map>
#include <string>
struct Command {};
struct Subtract : Command {};
struct Add : Command {};
class CommandFactory
{
public:
virtual Subtract * createSubtractionCommand() = 0;
virtual Add * createAdditionCommand() = 0;
};
class StackCommandFactory : public CommandFactory
{
public:
virtual Subtract * createSubtractionCommand(void);
virtual Add * createAdditionCommand(void);
Subtract * sub;
Add * add;
};
Subtract * StackCommandFactory::createSubtractionCommand(void) { return sub; }
Add * StackCommandFactory::createAdditionCommand(void) { return add; }
class CommandGetterImpl
{
public:
virtual CommandGetterImpl* clone() const=0;
virtual Command* get()=0;
virtual ~CommandGetterImpl() {};
};
class CommandGetter
{
public:
Command* get() { return impl_->get(); }
~CommandGetter() { delete impl_; }
CommandGetter( const CommandGetter & other ) : impl_(other.impl_?other.impl_->clone():NULL) {}
CommandGetter& operator=( const CommandGetter & other ) {
if (&other!=this) impl_= other.impl_?other.impl_->clone():NULL;
return *this;
}
CommandGetter() : impl_(NULL) {}
CommandGetter( CommandGetterImpl * impl ) : impl_(impl) {}
CommandGetterImpl * impl_;
};
class Parser
{
public:
Parser (CommandFactory & fact);
std::map<std::string, CommandGetter > operations;
};
template<typename MEMFN, typename OBJ >
class MemFnCommandGetterImpl : public CommandGetterImpl
{
public:
MemFnCommandGetterImpl(MEMFN memfn, OBJ *obj) : memfn_(memfn), obj_(obj) {}
MemFnCommandGetterImpl* clone() const { return new MemFnCommandGetterImpl( memfn_, obj_) ; }
Command* get() { return (obj_->*memfn_)(); }
MEMFN memfn_;
OBJ * obj_;
};
template< typename MEMFN, typename OBJ >
CommandGetter my_bind( MEMFN memfn, OBJ * obj )
{
return CommandGetter( new MemFnCommandGetterImpl<MEMFN,OBJ>(memfn,obj) );
};
Parser::Parser(CommandFactory & fact)
{
operations["+"] = my_bind(&CommandFactory::createAdditionCommand, &fact);
operations["-"] = my_bind(&CommandFactory::createSubtractionCommand, &fact);
}
#include <iostream>
int main()
{
Add add;
Subtract sub;
StackCommandFactory command_factory;
command_factory.add = &add;
command_factory.sub= ⊂
Parser parser(command_factory);
std::cout<<"&add = "<<&add<<std::endl;
std::cout<<"Add = " << parser.operations["+"].get() <<std::endl;
std::cout<<"&sub = "<<&sub<<std::endl;
std::cout<<"Sub = " << parser.operations["-"].get() <<std::endl;
return 0;
}
You need an explicit cast on the 2nd parameter of the bar instance:
Function<CommandFactory> bar(&fact,
reinterpretet_cast<Command *(CommandFactory::*)()>(&CommandFactory::createAdditionCommand));
Besides, you're missing parens for the method pointer attribute in Function:
Command * (T::*fptr)();
This error might have prevented you to find the solution above.
You are also missing the return keyword in the operator() there (a mistake that I often do because of my functional programming habits):
virtual Command * operator()(){
return (obj->*fptr)();
}
You can avoid the cast by making the return type a template parameter:
template <class T, typename D>
class Function : public Functor {
private:
D * (T::*fptr);
T* obj;
public:
Function(T* obj, D * (T::*fptr)()): obj(obj), fptr(fptr){}
virtual Command * operator()(){
return (obj->*fptr)();
}
};
void Foo(CommandFactory & fact){
Function<CommandFactory, Addition> bar(&fact, &CommandFactory::createAdditionCommand);
}
Note that I did not templatize Functor after all. While it seemed a good idea at first to me, it make things a bit more complex. If you wish to make Functor a template too, the return type will have to be exactly the same, you cannot use an inheritance relation between them, unless you make them both parameters of the Function template. As a rule of thumb, whenever you stumble on a template issue like that, remember that template are like C macros at the core, it's a rewriting mechanism, which will expand the template into real C++ types (functions or classes) separately. You can picture the problem that way:
template <typename T, typename D>
class Function : public Functor<D> { /* ... */ };
will be expanded to
class Function<CommandFactory, Addition> : public Functor<Addition> {
/* ... */
};
Functor<Addition> and Functor<Command> bears no relationship at all; these are two different classes.
If C++ template did carry the notion of bounded polymorphism (like in Java or C#), it could have perhaps been possible to write it in way close to your intent.
I recommend:
keeping the Functor a simple class, to make the code simpler to work with for the time being, and
if the need arises later on, trying to refactor a working version with that new feature.
Generally speaking, it's a bad idea to use member function pointers as opposed to std::function. More generally,
typedef std::function<void()> Command;
typedef std::function<Command()> Functor;
Really, there's absolutely no need whatsoever for any member function pointers in your code.

Adding methods to template specialization

I have a templated C++ class that exposes a number of methods, e.g
template<int X, int Y>
class MyBuffer {
public:
MyBuffer<X,Y> method1();
};
Now, I want to expose additional methods to this class if X == Y. I have done this by subclassing MyBuffer,
template<int X>
class MyRegularBuffer : public MyBuffer<X,X> {
public:
MyRegularBuffer method2();
};
Now, the problem is that I want to be able to do e.g.
MyRegularBuffer<2> buf = ...
MyRegularBuffer<2> otherBuf = buf.method1().method2();
But I am not sure how to accomplish this. I tried to think of copy constructors, conversion operators, etc, but my C++ skills are unfortunately a bit rusty.
EDIT: I should add that creation of these objects is relatively cheap (and also, it won't happen a lot), which means it would be OK to do something like this:
MyRegularBuffer<2> buf = ...
MyRegularBuffer<2> temp = buf.method1(); // Implicit conversion
MyRegularBuffer<2> otherBuf = temp.method2();
The question is then, how can I define the conversion like that. The conversion operator needs to be in MyBuffer, I think, but I want it to be available only if X==Y.
You don't need a separate class to represent the special behaviour. Partial specialization allows you to treat some of the MyBuffer <X,Y> cases specially and give them extra methods.
Keep your original declaration of MyBuffer<X,Y> and add this:
template<int Y>
class MyBuffer<Y, Y> {
public:
MyBuffer<Y,Y> method1();
MyBuffer<Y,Y> method2();
};
MyBuffer<1,2> m12; m12.method2(); // compile fail, as desired, as it doesn't have such a method because 1 != 2
MyBuffer<2,2> m22; m22.method2(); // compile success
Edit: my final lines weren't very useful after all, as pointed out by Georg in the comments, so I've deleted them.
I'd go for CRTP here:
template<int X, int Y, class Derived>
struct MyBufferBase {
// common interface:
Derived& method1() { return *static_cast<Derived*>(this); }
};
template<int X, int Y>
struct MyBuffer : MyBufferBase<X, Y, MyBuffer<X,Y> > {
// basic version
};
template<int X>
struct MyRegularBuffer : MyBufferBase<X, X, MyRegularBuffer<X> > {
// extended interface:
MyRegularBuffer& method2() { return *this; }
};
It's possible to do what you want if method1 and method2 return a reference to *this. Otherwise, you're going to need to either do a conversion, or make method1 virtual.
The trick is to have a MyRegularBuffer::method1 that calls MyBuffer::method1, then a way to convert the resultant MyBuffer<X,X> into a MyRegularBuffer<X>:
template<int X>
class MyRegularBuffer : public MyBuffer<X,X>
{
public:
MyRegularBuffer<X>()
{}
MyRegularBuffer<X>(MyBuffer<X,X>)
{
// copy fields, or whatever
}
MyRegularBuffer<X> method2();
MyRegularBuffer<X> method1()
{
MyRegularBuffer<X> ret(MyBuffer<X,X>::method1());
return(ret);
}
};