How can I implement this fluent interface in C++:
class Base {
public:
Base& add(int x) {
return *this;
}
}
class Derived : public Base {
public:
Derived& minus(int x) {
return *this;
}
}
Derived d;
d.add(1).minus(2).add(3).minus(4);
Current code doesn't work since Base class doesn't know anything about Derived class, etc. I would be very thankful for a hint/suggestion.
Make Base class templated. Use the wanted return type of Base the template type, like this:
template <typename T>
class Base {
public:
T& add(int x) {
return *static_cast<T *>(this);
}
}
Then inherit Derived from Base like this:
class Derived : public Base<Derived>
Alternatively (as an answer to Noah's comment), if you don't want to change Base, you could use an intermediate class that performs the casting, like this:
template <typename T>
class Intermediate : public Base {
public:
T& add(int x) {
Base::add(x);
return *static_cast<T *>(this);
}
}
And let Derived inherit from Intermediate:
class Derived : public Intermediate<Derived>
This interface is not possible in C++. You must either make minus() a virtual function within Base or use non-member functions that do some form of type detection.
Don't pull up minus() unless it makes sense in terms of Base.
The problem is on your function
Base& add(int x);
This is similar to the operator+=(), which must also be overridden to work seamless.
You need to override this function on the derived class.
class Derived : public Base {
public:
Derived& minus(int x) {
return *this;
}
Derived & add(int x) {
return static_cast<Derived &>(this->Base::add(x));
}
}
in this way d.add(1) will return a reference to d.
Related
I have several c++ classes that have similar behaviours. Moreover most of the class methods can be constructed from few fundamental ones. So I want to define a base class with the derived methods, inherit from the base class and define the remaining methods in the derived classes.
This is my attempt using the CRTP
template <class derived_class> class base_class {
public:
virtual derived_class& operator++ () = 0;
virtual derived_class& fun1() = 0;
derived_class operator++ (int) {
derived_class toreturn(static_cast<derived_class&>(*this));
++*this;
return toreturn;}
derived_class& fun2() {
this->fun1();
return static_cast<derived_class&>(*this);
};
};
class deriv1 : public base_class<deriv1> {
public:
int n;
deriv1():n(0){};
deriv1(deriv1& other):n(other.n){};
deriv1& operator++ () override { ++n; return *this;}
deriv1& fun1() override { n *= n; return *this;}
};
I don't understand why fun2() works but not the postscript increment.
If I call the postscript increment on a derived object I get the error message "Cannot increment value of type 'deriv1'".
The solution is to add a using statement:
class deriv1 : public base_class<deriv1> {
public:
....
using base_class::operator++;
};
The problem is that function resolution is failing. Lets think of a simpler solution to illustrate the problem:
struct Base
{
void f() {}
void f(int) {}
};
struct Derived: public Base
{
void f() {}
};
int main()
{
Derived a;
a.f(1); // This fails as there is no f() that takes an integer
// in Derived. And since the compiler found an f() in
// Derived it stopped looking further up the chain
// for additional matches.
}
This problem is solved in the same way.
struct Derived: public Base
{
using Base::f;
void f() {}
};
I have two classes, let's say Base and Derived:
class Base {
public:
virtual ~Base() = 0;
};
class Derived : public Base {};
and a function foo:
auto foo (Derived* d) {
...
}
Is it possible to automatically downcast its argument? So I could do something like this:
Base* b = new Derived();
foo(b);
Basically I would like to write this without explicit casting it before function call.
I read something about conversion operators/constructors but they seem not useful in my case, do you have any other idea?
Edit: Sorry, I oversimplified the question with 2 classes and just a function. But actually I've got a library of 50-ish functions and 3 classes (a superclass and 2 subclasses). This unfortunately makes the easiest and cleanest solutions unsuitable because in my opinion (correct me if I am wrong) they scale bad.
I can think of three possible solutions, depending on your needs. I've replaced raw pointers with unique_ptrs in my examples.
Case 1: You don't need the base type of each derived type to be the same.
Use CRTP to allow the base type to invoke itself as a derived type. Example implementation:
template <typename DerivedType>
class Base {
template <typename F>
auto invoke_as_derived(F&& f) {
return std::forward<F>(f)(static_cast<DerivedType*>(this));
}
};
class Derived : public Base<DerivedType> {};
Usage:
std::unique_ptr<Base<Derived>> b = std::make_unique<Derived>();
b->invoke_as_derived(foo);
Since you mentioned using a list of Base pointers, this probably won't work for you.
Case 2: You need a shared base type but only have one layer in your type hierarchy and no virtual methods.
Use std::variant and std::visit.
class Derived {};
using Base = std::variant<Derived, /* other derived types */>;
auto foo(Derived*) { ... }
class FooCaller {
operator ()(Derived& d) {
return foo(&d);
}
// Overload for each derived type.
}
Usage:
Base b = Derived();
std::visit(FooCaller{}, b);
Case 3: You need a single base type but also want virtual methods and/or additional layers in your type hierarchy.
You might try the visitor pattern. It takes some boilerplate, but it may be the best solution depending on your needs. Sketch of the implementation:
class Visitor; // Forward declare visitor.
class Base
{
public:
virtual void accept(Visitor& v) = 0;
};
class Derived : public Base
{
public:
void accept(Visitor& v) final { v.visit(*this); }
};
struct Visitor
{
virtual void visit(Derived&) = 0;
// One visit method per derived type...
};
struct FooCaller : public Visitor
{
// Store return value of call to foo in a class member.
decltype(foo(new Derived())) return_value;
virtual void visit(Derived& d)
{
return_value = foo(&d);
}
// Override other methods...
};
Usage:
std::unique_ptr<Base> b = std::make_unique<Derived>();
FooCaller foo_caller;
b->accept(foo_caller);
You could write a visitor that takes a function to apply to the element so you don't have to repeat this for all of your many functions. Alternatively, if you can alter the functions themselves, you could replace your functions with visitor types.
Edit: Simplifying the call syntax back down to foo(b)
Define an overload per function overload set to which you want to pass Base objects. Example, using the 3rd technique:
auto foo(Base* b) {
FooCaller foo_caller;
b->accept(foo_caller);
return std::move(foo_caller.return_value);
}
Now foo(b.get()) will delegate to the appropriate overload of foo at run-time.
The usual approach would not be to downcast, but to use virtual functions. I.e. put void foo() inside of the class.
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() { std::cout << "Base foo()\n"; }
};
class Derived : public Base {
public:
void foo() override { std::cout << "Derived foo()\n"; }
};
int main()
{
Base* b = new Derived();
b->foo();
delete b;
}
outputs:
Derived foo()
If you want to make it impossible to call Base::foo(), you can set
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
making Base an abstract class.
But if you really want to call foo(b), you can use a (templated) helper function. E.g.:
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Derived foo()\n";
}
};
template<typename T>
void foo(T* t)
{
t->foo();
}
int main()
{
Base* b = new Derived();
foo(b);
delete b;
}
This is a recurrent problem once again. Someone know a easy way to do that? Imagine I have the following:
class Base
{
public:
...
Base property(const std::string& name)=0;
};
class Derived:public Base
{
public:
Derived();
Derived(const Derived&& val);
Base property(const std::string& name)
{
Derived z;
return z;
}
}
There is a way for the Derived::property return being (internally) a Derived copy instead of only Base part copy, and with the Derived move constructor invoked?
May be a stupid question, but really I dont find solution. Why copy constructors on return dont copy the specialized class?
Thanks you!
You can't do this.
Returning by value conceptually (ignoring RVO and move semantics) means making a copy of whatever you return by using the copy constructor of the type which the function is declared to return. If you return a Derived, a copy of type Base will be made and you'll lose the Derived part of the object. This is known as slicing.
If you want to return a Derived object as a Base, you'll need to use pointers.
The only aproximation I can find for who search something similar (related with X3liF, TartanLlama and other responses)
#define overridable(T) ovr<T>
#define return_overload_allowed(TYPE) friend struct ovr<TYPE>; virtual void* clone() const
#define return_overload_basic_allowed(TYPE) friend struct ovr<TYPE>; virtual void* clone() const{return new TYPE(*this);}
template<typename T> struct ovr
{
T* _obj;
ovr(const T& t)
: _obj(reinterpret_cast<T*>(t.clone()))
{;}
ovr(ovr<T>&& v)
: _obj(v._obj)
{
v._obj=nullptr;
}
operator T&()
{
return *_obj;
}
virtual ~ovr()
{
delete _obj;
}
};
class BASE
{
return_overload_basic_allowed(BASE);
public:
virtual overridable(BASE) method1();
virtual ~BASE();
};
class DERIVED: public BASE
{
return_overload_basic_allowed(DERIVED);
public:
virtual overridable(BASE) method1()
{
DERIVED a;
return a;
}
virtual ~DERIVED();
};
DERIVED a;
auto x = a.method1();
BASE& really_derived = x;
This compiles fine. But don't meet practical and smart requiriments... :(
I tried using CRTP with this (simplified) example:
Base class:
template <class Derived>
class Base
{
public:
int method(int in, int& out2)
{
return derived().method(in, out2);
}
int method(int in)
{
int dummy;
return this->predict(in, dummy);
}
protected:
Base() {}
private:
Derived& derived()
{
return *static_cast<Derived*>(this);
}
};
Derived class:
class Derived : public Base<Derived>
{
public:
int method(int in, int& out2)
{
// Logic here
}
};
The problem is, when I try to use method(int in) with an instance of the Derived class, like:
Derived d;
int res = d.method(5);
The compiler (icc in this case, but have also tried with msvc) gives me the following error:
error #165: too few arguments in function call
It seems that the compiler is not realizing that there exists an overload which only takes one parameter, from the Base<Derived> class (from which Derived inherits publicly, so I think it should be accesible).
I'm not sure what I'm missing here, any hints will be deeply appreciated.
The presence of Derived::method means that the compiler will not consider overloads of Base::method when attempting to bind the call. To fix this, add using Base::method; to the derived class:
class Derived : public Base<Derived>
{
public:
using Base::method;
int method(int in, int& out2)
{
// Logic here
}
};
When a non-virtual function is defined with the same name as a Base::method, it overshadows the Base::method in the Derived class, which is also known as Name Hiding.
To prevent this, you have to explicitly mention the name of the method with the class using the using operator, i.e. your Derived class code should be modified to:
class Derived : public Base<Derived>
{
public:
using Base::method; //makes the 'method' declaration of Base class
//visible here as well.
int method(int in, int& out2)
{
// Logic here
}
};
I have searched far and wide for a specific answer to this question, and cannot find it. I am trying to create a base class with a virtual operator> that I can override in the derived class. Currently I'm having problems because declaring the function only requires one input variable (as in "bool operator> (Derived & a)" but attempting to define it in a cpp file tells me that it requires two inputs (as in "bool operator> (Derived & a, Derived & b))
I've tried defining the operator inline, but then I get errors where it thinks the derived class is still abstract because I'm passing in the derived type to the operator as shown above, instead of the base class. But if I pass the base class, then I cannot access the derived member variables I need to make the comparison.
I think I'm missing something simple here but I cannot seem to figure out what it is.
Hopefully you can help.
Thanks
For virtual calls to work from a reference/pointer of the base, you will need to use the base-type in the function, so for example
class Derived : public Base
{
....
bool operator>(Base &a)
{
Derived *pa = dynamic_cast<Derived *>(&a);
return this->something > pa->something; // Or whatever...
}
....
};
If you change the type, it becomes a different function, and when you use the base pointer or reference to refer to operator>, it will use the one in the base-class.
Why don't you leave operator>() non-virtual, und have it call a private virtual function?
Like so:
class Base {
public:
bool operator>(Base &a) {
return implementingFunction(a);
}
private:
virtual bool implementingFunction(Base &a) = 0;
};
#include <iostream>
using namespace std;
class base{
public :
virtual bool operator> (base& obj) { cout<<"b\n";return true;}
virtual ~base(){}
};
class derived: public base{
public:
virtual bool operator> (derived& obj) { cout<<"d\n";return true;}
~derived(){}
};
int main()
{
base *a=new derived(),b;
if(*a>b) { delete a; cout<<"Done!\n"; }
return 0;
}
Old question, but I've hardly seen a useful/correct answer here, so I would add my suggestion:
struct base
{
virtual ~base() = default;
virtual bool operator> (base const& obj) const = 0;
};
struct derived: public base
{
derived(int member) : member(member) {}
int member = 0;
virtual bool operator> (base const& obj) const
{
return member > static_cast<derived const&>(obj).member;
}
};
int main()
{
//in reality one would use a unique_ptr, of course
base* a = new derived(1);
base* b = new derived(0);
if(*a > *b)
{
//do something
}
return 0;
}
Caution: this works safely only if you're sure that the base const& parameter is really a derived const& (as e.g. in CRTP).
If not, you should use a dynamic_cast and add some error handling.