I've got some problems with my lamba expressions: I have a class that owns a function pointer.
class SomeClass
{
void (*execFunc)(Base*);
}
And I have a Base class:
class Base
{
SomeClass* someClass;
void doSomething() { someClass->execFunc(this); }
}
From this one I derive lots of other classes whose execFuncs will be different. Therefore I want to use lambda-expressions; e.g:
class Derived final : public Base
{
int someDerivedAttrib;
static List<SomeClass*> someClasses = createSomeClasses(); // holds all possible
// SomeClasses for this
// derived class
static List<SomeClass*> createSomeClasses()
{
List<SomeClass*> scs;
SomeClass* sc = new SomeClass();
sc->execFunc = [] (Derived* derived) { derived->someDerivedAttrib = 10; };
scs << sc;
return scs
}
}
But unfornately this won't work since cast from void (*)(Derived*) to void (*)(Base*) is not possible. Any suggestions, except making a cast form Base* to Derived* in every lambda-function?
Expecting ye answers,
Albjenow
How about, instead of SomeClass being a regular class, making it a the base class of a class template that handles having the proper functor type, as well as downcasting to the right type ?
It would look like this:
class SomeClass
{
virtual void callFunc(Base*) = 0;
}
template<typename T>
class SomeDerivedClass : public SomeClass
{
static_assert(std::is_base_of<Base, T>::value, "SomeDerivedClass: unexpected base class");
virtual void callFunc(Base* b) override
{
execFunc(static_cast<T*>(b));
}
void (*execFunc)(T*);
}
Base then becomes:
class Base
{
SomeClass* someClass;
void doSomething() { someClass->callFunc(this); }
}
Then, in your Derived definition:
class Derived final : public Base
{
int someDerivedAttrib;
typedef SomeDerivedClass<Derived> tSomeClass;
static List<tSomeClass*> someClasses = createSomeClasses(); // holds all possible
// SomeClasses for this
// derived class
static List<tSomeClass*> createSomeClasses()
{
List<tSomeClass*> scs;
tSomeClass* sc = new tSomeClass();
sc->execFunc = [] (Derived* derived) { derived->someDerivedAttrib = 10; };
scs << sc;
return scs
}
}
However, this runs the risk of calling SomeDerivedClass::call with the wrong concrete class.
Wouldn't this do the trick?
sc->execFunc = [] (Base* base) { static_cast<Derived*>(base)->someDerivedAttrib = 10;
After all you have to respect the original signature of the execFunc pointer.
Related
Is there a way to force implementation of a method in a child class where the implementation will have a different signature for each derived class?
I know I can do this, using pure virtual:
class Base {
public:
virtual void getValue(string& s) = 0;
}
class Derived : public Base {
public:
void getValue(string& s);
}
Above, pure virtual getValue in the base class forces the derived class to implement getValue. But what I really want to do is something like this: Force each derived class to implement getValue() but each with a different signature:
class Base {
public:
void getValue() = 0;
}
class Derived_A : public Base {
public:
void getValue(string& s);
}
class Derived_B : public Base {
public:
void getValue(int *j);
}
The problem with the above is that, due to name mangling, each signature is effectively a different function, and thus Derived_A and Derived_B inherit getValue() = 0 and the compiler thinks that they also are abstract.
I've been playing around with some different ways to do this, but it appears to me there is no way to do it. I'm thinking I should simply not declare getValue in the Base class and then just make sure each derived class implements their version of it.
If use of CRTP would work for you, you can use:
#include <string>
template <typename TypeSelector>
class Base {
public:
using type = typename TypeSelector::type;
virtual void getValue(type t) = 0;
};
struct TypeSelector_A {
using type = std::string&;
};
class Derived_A : public Base<TypeSelector_A> {
public:
void getValue(std::string& s) { /* Add real implementation */ }
};
struct TypeSelector_B {
using type = int*;
};
class Derived_B : public Base<TypeSelector_B> {
public:
void getValue(int* j) { /* Add real implementation */ }
};
int main()
{
Derived_A a;
Derived_B b;
}
But what I really want to do is something like this: Force each derived class to implement getValue() but each with a different signature
The whole point of having virtual function (abstract or not) is that you can use it with pointer or reference to the base class which means you would use signature of the function from the base class. With that having what you want is completely useless. What you want can be implemented by returning std::variant or std::any with every virtual function in tree so keeping signature the same.
You should think how would you use such concept if it would be possible. If you think somethink like this:
void foo( Base *b ) {
if( auto *d = dynamic_cast<Derived_A *>( b ) ) {
std::string str;
d->getValue( str );
...
}
if( auto *d = dynamic_cast<Derived_B *>( b ) ) {
int i = 0;
d->getValue( &i );
...
}
}
then getValue() does not need to be virtual, you only need vritual destrictor in Base. But this is considered bad design.
I am using pure virtual functions and interfaces for the first time but having some troubles, probably because i did not fully understand some of the basics.
In the main function, i am trying to create an object "a" of a derived class which is creating another object "obj" inside the class and sets a member variable of obj to some value.
Later in the main function, i want to print the member variable of obj.
The Error class "AbstractB" has no member "setVar" occurs in DerivedA.h .
The setVar function is not part of the abstract class because in different derived classes var may have different data types.
AbstractA.h
class AbstractA
{
public:
AbstractA() {}
virtual ~AbstractA() {}
virtual void buildObj() = 0;
AbstractB* getObj() { return obj; }
protected:
AbstractB* obj;
};
AbstractB.h
class AbstractB
{
public:
AbstractB() {}
virtual ~AbstractB() {}
virtual void doSthWithVar() = 0;
// All derived classes have a private member variable var of varying data types
};
DerivedA.h
class DerivedA: public AbstractA
{
public:
// buildObj() creates some numbers e.g. 1
void buildObj() { obj->setVar( 1 ); } // Error due to calling the function using the abstract class instead of the derived one
};
DerivedB.h
class DerivedB
{
public:
void setVar( int i ) { var = i; }
void doSthWithVar(){ std::cout << var << std::endl; }
private:
int var;
};
main.cpp
int main()
{
DerivedA a;
a.buildObj(); // Creating a DerivedB object which is holding a variable var
// I want to do something like this
AbstractB* obj = a.getObj();
obj->doSthWithVar(); // Should print 1
}
Is there any way to call the setVar() function in DerivedA.h to allow later retrieval of var without disturbing the structure of the abstract classes?
EDIT:
I implemented the solution from Robert Andrzejuk in the following way:
class DerivedA: public AbstractA
{
public:
void buildObj()
{
DerivedB* b = new DerivedB();
b->setVar( 1 );
obj = b;
}
};
I don't see where You have created an instance of DerivedB?
The most logical place looks like in DerivedA.
And that's where You have all the info to call the needed functions.
class DerivedA: public AbstractA
{
DerivedB b;
public:
// buildObj() creates some numbers e.g. 1
void buildObj()
{
b.setVar( 1 );
obj = &b;
}
};
I have a situation that I am attempting to write some c++ code to implement and I think I need to use templates but I am unsure. I don't think I understand templates well enough and just want to know if I am on the right track. I have never implemented a class that requires templates before.
I have a base class that needs to instantiate a new class and store it on a list for future access. The class that needs to be instantiated is derived from a base class that has one virtual method. After the class is instantiated, this method is called and the new instance is stored on a list. Another method is provided to get the instantiated object.
Say the virtual class is named foo:
class foo
{
public:
virtual void process() = 0;
}
the user would create a class bar:
class bar : public foo
{
public:
void process() {};
}
The class that I think needs to be a template class:
class Filter<Foo* T>
{
public:
// use value junk to derive foo
// and put the new instance on a std::list
add(Junk* junk);
T get();
private:
std::list<T> mFooList;
}
void Filter::add(Junk* junk)
{
T* foo = new T();
foo.p(junk);
mFooList.push_back(foo);
}
T* Filter::get()
{
if(!mFoolist.empty())
{
T* res = mFooList.back();
mFooList.pop_back();
return res;
}
return nullptr;
}
You don't need to use a templatevin this situation. In c++ a derived class can be assigned to a pointer of the base class. You can just use foo pointers.
class foo
{
public:
virtual void process();
};
class bar1: public foo
{
public:
void process();
};
class bar2 : public foo
{
public:
void process();
};
class filter
{
private:
std::list<foo*> _foos;
public:
foo* get();
void add(foo* f);
};
void filter::add(foo* f)
{
_foos.push_back(f);
}
foo* filter::get()
{
if(!_foos.empty())
{
return _foos.pop_back();
}
return nullptr;
}
You can then just add and get foos and bars
filter fil;
fil.add(new foo());
fill.add(new bar1());
fill.add(new bar2());
foo f = fill.get();
while(f != nullptr)
{
f->process();
delete f;
f = fil.get();
}
I'm wondering if there is anyway to do something like this pseudo code:
class A : public std::enable_shared_from_this<A> {
public:
std::shared_ptr<self_t> getPtr(){
return std::static_pointer_cast<self_t>(shared_from_this());
}
};
class B : public A {
std::vector<A> container;
std::shared_ptr<self_t> addChild(A child){
container.push_back(child);
return getPtr();
}
};
class C : public B {
public:
std::shared_ptr<self_t> doSomething(){
// something
return getPtr();
}
};
int main(){
A obja = new A();
C obj = new C();
obj->addChild(obja)->doSomething()
}
My goal is that an object represents a view (as in the V in MVC), and for methods to be able to return itself for chained calling. Eg: ->setTop(0)->addChild(child1)->setBottom(0).
I've read that it may be more approachable to do something like overloading the << operator, but I don't see that working to well or looking very pretty.
One thought I had was to make a macro called VIEW(name,parent) that would use templates to expand out, but I had issue with self-refferental default template arguments.
Any help would be greatly appreciated.
-- edit --
In a nut shell, I'm hoping to have a base class inherit from enable_shared_from_this. The base class would have a method such as doSomething that returns the shared pointer. When a derived class inherits from the base class, I want the doSomething method to return a shared pointer to the derived class. I want to be able to do this without overriding doSomething in the derived class.
This kind of concept would be covered by extension methods which exist outside a class definition, do not violate the class permissions but can be called like a method... which exists in C# but not currently in C++. The code in C# looks like this:
// c# syntax
namespace MyBaseExtensions {
public static class MyBaseExt {
public static shared_ptr<T> getPtr<T>(this T self) where T : MyBase
{
return static_pointer_cast<T>(self.shared_from_this());
}
}
}
This allows for operator chaining because each inheritance of a class line MyBase would have its own definition of the function because the function is not an inherited method but instead applied directly to each related type.
The argument against is that extensions pollute the object with often unneeded functionality and that a standalone template function will do the same thing. The issue is that with that logic:
int main(){
A obja = new A();
C obj = new C();
obj->getPtr()->addChild(obja)->doSomething()
}
ends up looking like
int main(){
A obja = new A();
C obj = new C();
doSomething(addChild(getPtr(obj),obja)); //eyeroll.
}
and you would still be declaring the template functions such like
// C++ syntax
namespace MyBaseExtensions {
template<typename T> std::shared_ptr<T> getPtr<T>(T self)
{
return std::static_pointer_cast<T>(self->shared_from_this());
}
}
As for a simple internal way of applying a template uniquely to each derived type, I am not sure of any. The reason for this is that the functionality you want is not method inheritance but that each future class inherits a template which it automatically specializes(and of which the resulting method is either not inherited or hidden.) For that purpose C++ classes would need to have non-inherited specialized public methods, which are not covered by the current access permissions public, private, and protected or template capabilities.
I would be overjoyed to find a nice way to pull off operator chaining.
And since I have gone and wasted your time I made an attempt at this:
#include <vector>
#include <memory>
// 0 argument, creates an overload method (and hides parent class method)
// from template method func_name
// template method specialization of a parent method does not work
// so we use C++11 automatic type deduction to figure the
// template return type and return what the template returns
#define FUNC_DEF_0(base, cur, func_name) \
auto func_name() \
-> decltype(base().func_name<cur>()) { \
return base::func_name<cur>(); \
}
// 1 argument
#define FUNC_DEF_1(base, cur, func_name, arg1_t) \
auto func_name(arg1_t param1) \
-> decltype(base().func_name<cur>(param1)) { \
return base::func_name<cur>(param1); \
}
// class A
// add to class to hide class A methods
#define HIDE_A(current) \
FUNC_DEF_0(A, current, getPtr)
class A : public std::enable_shared_from_this<A> {
public:
template<typename _T = A>
std::shared_ptr<_T> getPtr(){
return std::static_pointer_cast<_T>(shared_from_this());
}
};
// class B
// add to class to hide class B methods with new methods
#define HIDE_B(current) \
HIDE_A(current) \
FUNC_DEF_1(B, current, addChild, A)
class B : public A {
public:
std::vector<A> container;
template<typename _T = B>
std::shared_ptr<_T> addChild(A child){
container.push_back(child);
return A::getPtr<_T>();
}
HIDE_A(B); // hide A methods with B specialized methods
// Example method hiding
// auto getPtr() -> decltype(A().getPtr<B>()) {
// return base::getPtr<B>();
// }
};
// class C
// add to class to hide class C methods
#define HIDE_C(current) \
HIDE_B(current) \
FUNC_DEF_0(C, current, doSomething)
class C : public B {
public:
template<typename _T = C>
std::shared_ptr<_T> doSomething(){
// something
return A::getPtr<_T>();
}
HIDE_B(C); // hide B methods
};
int main() {
auto obja = std::make_shared<A>();
auto obj = std::make_shared<C>();
obj->addChild(*obja)->doSomething();
}
Edit: Fixed attempt. Compiles for me.
class A;
struct virtual_enable_shared_from_this_base :
std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
virtual ~virtual_enable_shared_from_this_base() {}
};
#define HIDE_AMix(type) \
using type::getPtr;
template<typename _T>
class AMix : public virtual virtual_enable_shared_from_this_base {
public:
std::shared_ptr<_T> getPtr() {
auto sptr = shared_from_this();
return std::dynamic_pointer_cast<_T>(sptr);
}
};
#define HIDE_BMix(type) \
HIDE_AMix(type) \
using type::addChild;
template<typename _T>
class BMix : public AMix<_T>{
public:
std::vector<std::shared_ptr<A>> container;
std::shared_ptr<_T> addChild(A* child){
container.push_back(child->getPtr());
return getPtr();
}
};
#define HIDE_CMix(type) \
HIDE_BMix(type) \
using type::addChild;
template<typename _T>
class CMix : public BMix<_T>{
public:
std::shared_ptr<_T> doSomething(){
// something
return getPtr();
}
};
class A : public AMix<A> {
public:
};
class B : public A, public BMix<B> {
public:
HIDE_AMix(BMix<B>);
//using BMix<B>::getPtr;
//using BMix<B>::addChild;
};
class C : public B, public CMix<C> {
public:
HIDE_BMix(CMix<C>);
//using CMix<C>::getPtr;
//using CMix<C>::addChild;
//using CMix<C>::doSomething;
};
int main() {
auto obja = std::make_shared<B>();
auto obj = std::make_shared<C>();
obja->getPtr();
obj->addChild(obja.get())->doSomething();
}
Edit2: Here is another version from fiddling around with templates.
Here is an example of what you may be trying to accomplish (though I'm not sure I 100% understood your requirements or reasoning for this design). Hope it helps...
#include <iostream>
#include <memory>
#include <vector>
class MyBase;
typedef std::shared_ptr<MyBase> MyBaseSharedPtr;
class MyBase : public std::enable_shared_from_this<MyBase> {
public:
MyBaseSharedPtr getPtr() { return shared_from_this(); }
virtual MyBaseSharedPtr doSomething() { return getPtr(); };
virtual MyBaseSharedPtr addChild(MyBaseSharedPtr child) { return getPtr(); };
};
class MyDerived1 : public MyBase {
private:
std::vector<MyBaseSharedPtr> container;
public:
MyBaseSharedPtr addChild(MyBaseSharedPtr child) {
container.push_back(child);
std::cout << "class MyDerived1: adding child\n";
return getPtr();
};
virtual MyBaseSharedPtr doSomething() {
std::cout << "class MyDerived1: doing something\n";
return getPtr();
}
};
class MyDerived2 : public MyDerived1 {
public:
MyBaseSharedPtr doSomething() {
std::cout << "class MyDerived2: doing something\n";
return getPtr();
}
};
int main(void ) {
MyBaseSharedPtr myBase = std::make_shared<MyBase>();
MyBaseSharedPtr myDerived2 = std::make_shared<MyDerived2>();
myDerived2->addChild(myBase)->doSomething();
return 0;
}
template<typename _T>
shared_ptr<_T> allocate()
{
shared_ptr<_T> ptr(new _T);
// this may need to be changed to
// something like (*typename ptr.get()).weak_this
// if the compiler won't accept a duck-typed _T::weak_this
ptr.get()->weak_this = weak_ptr<_T>(ptr);
return ptr;
}
class A
{
weak_ptr<A> weak_this;
friend shared_ptr<A> allocate<A>();
public:
shared_ptr<A> getPtr(){return weak_this.lock();}
shared_ptr<A> doSomething()
{
// do something
return getPtr();
}
};
Based on your example, if what you really want is to be able to extend functionality without exploding multiple inheritance hierarchies and without overwriting each method everywhere, you could try composed functionality with templates. Something like this:
#include <list>
#include <iostream>
struct Base {
};
template <class Parent>
struct A : Parent {
std::list<Parent*> children;
A* addChild(Parent* child) {
children.push_back(child);
return this;
}
};
template <class Parent>
struct B : Parent {
B* doSomething() {
std::cout << "Something" << std::endl;
return this;
}
};
int main(){
typedef A< B<Base> > Composed;
Composed a;
Composed b;
a.addChild(&b)->doSomething();
}
Note, however, that this has the restriction that forces a use order based on the order you compose the "functionality" (classes).
That is, in this example, you can't do:
a.doSomething()->addChild(&b); //ERROR! B is not a A
But this would work if you declare:
typedef B< A<Base> > Composed; //Note the order of B and A
I don't know if it suits your needs.
Hope this helps, at least, to enable you to think the problem in a different way.
Here is what I am trying to achieve:
I have a list of Classes (Class1 to Classn) which inherit from a main Class
I would like to be able to instanciate an object of any of the n classes without having to do a large switch case (or equivalent). something along the lines of:
static ClassPointerType const * const ArrayOfClassTypes[]={ Class1, Class2, .. Classn };
static Class *GetObjectOfClass(int i)
{
return new ArrayOfClassTypes[i](some parameters for the constructor);
}
You can do that in other OO langues like Delphi where you have a TClass type and can get the class of an object... but I was not able to locate the equivalent functionality in C++.
Are you looking for something like this?
template<typename T>
std::unique_ptr<base> make()
{
return std::unique_ptr<base>(new T);
}
class factory
{
static constexpr std::unique_ptr<Base> (*fns[])(){make<derived_a>, make<derived_b>};
std::unique_ptr<base> get_object_of_class(int const i)
{
if (i < 0 || sizeof fns / sizeof *fns <= i) {
return nullptr;
}
return fns[i]();
}
};
You can add virtual method Clone to your base class and have it pure virtual (= NULL). Have there all required parameters.
Then you can override it in every subclass and create concrete classes there.
And in your factory do:
static ClassPointerType *GetObjectOfClass(int i)
{
return new ArrayOfClassTypes[i]->Clone(some params for the constructor);
}
And your array should contain concrete classes which you will clone:
static ClassPointerType* const ArrayOfClassTypes[]={ new ClassPointerType1(),new ClassPointerType2(), .. new ClassPointerTypeN() };
Complete example as requested:
// base class
class ClassPointerType
{
…
public:
virtual ClassPointerType* Clone(your params) = NULL;
};
// concrete classes
class ClassPointerType1 : public ClassPointerType
{
…
public:
// note: it clones own concrete instance
virtual ClassPointerType* Clone(your params) {return new ClassPointerType1(your params)};
}
class ClassPointerType2 : public ClassPointerType
{
…
public:
virtual ClassPointerType* Clone(your params) {return new ClassPointerType2(your params)};
}
…
class ClassPointerTypeN : public ClassPointerType
{
…
public:
virtual ClassPointerType* Clone(your params) {return new ClassPointerTypeN(your params)};
}
I implemented something alike recently. In my approach I stored a list of static create-functions instead and feeded a factory class with that
I implemented a templated base class wich
a) is able to register the derived into a factory class
b) implicitly forces the derived class to provide static functions.
However, you have to announce each derived class once. You can use it like this:
int main(int argc, char* argv[])
{
DerivedA::announce();
//and later
IInterface * prt = SingeltonFactory::create(DerivedA::_type);
delete prt;
return 0;
}
The Derived class DerivedA is defined as:
class DerivedA :
public IInterface,
public StaticBase<DerivedA>
{
public:
using StaticBase::announce;
static IInterface * create(){ return new DerivedA; }
static const std::string _type;
};
const std::string DerivedA::_type=std::string("DerivedA");
And the static Base class forcing the _type attribute and the create function to exist are defined as follows:
template<class TDerived>
class StaticBase
{
protected:
static void announce()
{
// register into factory:
SingeltonFactory::registerFun(TDerived::_type,TDerived::_create());
// The call of _type and _create implicitly forces the derived class to implement these, if it is deriving from this Base class
}
};
The factory class does contain a map of
std::map<std::string,tFunPtr>
where typedef tFunPtr is:
typedef IInterface * (*tFunPtr)(void);
This map you can use as an "array of classes" in order to handle it like an object. Thus, you represent the classes by a function pointer of the static create function
Does this answer your requirements? Shall I provide the factory class?
Assuming you are using a C++11 compiler here is a solution equivalent to the one provided earlier but less tricky and clever:
#include <iostream>
#include <memory>
#include <array>
class Base {
public:
virtual void doSomething() = 0;
};
class Der1: public Base {
private:
void doSomething() override {
std::cout << "Der1 did something" << std::endl;
}
};
class Der2: public Base {
private:
void doSomething() override {
std::cout << "Der2 did something" << std::endl;
}
};
template <typename T>
std::unique_ptr<Base> make() {
return std::unique_ptr<T>(new T);
}
int main() {
std::array<std::function<std::unique_ptr<Base>(void)>, 2> arr{make<Der1>,
make<Der2>};
auto obj = arr[0]();
obj->doSomething();
obj = arr[1]();
obj->doSomething();
}
You can use std::bind too to pass arguments to make if you have to use a non-default contructor
Hope that helps
No, in C++ classes are not first-order entities.
(I just noticed everybody is providing a solution to your problem but not precisely answering your question.)