So I have a program in which I have a function that needs to be passed as an argument to another function call. So I was running a Test Case. Let's say there are two classes Abstract and Concrete, the latter one being the child class of earlier.
// This enum is designed to distinguish between 'int', 'real', and 'bool' types
enum myTypes { i, r, b };
// This helper function converts from a type to one of the above enum values
proc typeToEnum(type t) {
select t {
when int do
return myTypes.i;
when real do
return myTypes.r;
when bool do
return myTypes.b;
otherwise
compilerError("Unexpected type in typeToEnum()");
}
}
// This is an abstract class that isn't good for much other than
// supporting the ability to mix various sub-class instantiations
// within a data structure.
//
class AbstractDataArray {
// This stores information sufficient for determining a concrete
// subclass's static type
var concType: myTypes;
const rank: int;
// This is its initializer
proc init(type t,rank) {
this.concType = typeToEnum(t);
this.rank = rank;
}
// This is a dynamically dispatched method
proc printMe() {
writeln("I am a generic Abstract class");
}
}
// This is a concrete class that contains everything important through
// generic fields
//
class Concrete: Abstract {
type t; // the type of elements stored
var x: t; // an example element of that type
// The class's initializer
proc init(x) {
super.init(x.type);
this.t = x.type;
this.x = x;
}
// The class's override of the dynamically dispatched method
override proc printMe() {
writeln("I am a Concrete class with type ", t:string, " and value ", x);
}
// This is a non-dynamically dispatched method, because its return
// type will vary across classes in the hierarchy, so it can't be
// inherited.
//
proc getValue() {
return x;
}
}
and the function which I need to pass as an argument is as follwing
proc rhs(u:shared Abstract,t:real){
// Does some stuff by changing abstract to one of concerete types
// returns rh which is object of class Concerete typecasted to class Abstract
return rh:Abstract;
}
var a = rhs;
a(U_0,1.20); // Assume U_0 has been defined somewhere above and is an object of class Concerete
And upon running the last code, the output is
Tests/sphinx_solvingPDE.chpl:81: error: in call to 'this', cannot pass result of coercion by reference
Tests/sphinx_solvingPDE.chpl:81: note: implicit coercion from 'shared DataArray(real(64),1,false)' to 'shared AbstractDataArray'
Tests/sphinx_solvingPDE.chpl:80: note: when passing to 'const ref' intent formal 'u'
So the solution to above problem was simple. I typecasted the variable to Abstract and then passed it to function, instead of directly passing it.
var arg = U_0:AbstractDataArray;
a(arg,1);
Related
My parent class holds two functions: On is supposed to be overwritten by the child, the second (same name) just uses as input a different type and than uses the overwritten method. Now I understand that if I define in the child class a method with the same name and same input parameters, it will shadow (is that the right expression?) the parents method. But I can still call the parents method by calling it explicit like: b.A::getSize(...).
My question is: Why does the parent method get shadowed even if the input parameter types are different? Why can't the compiler find the parent method with the correct input types? See the below minimal example.
And bonus question: Is it possible to achieve the behaviour that I can call the parents method without the need of the explicit call and without modifying main(){...} nor class B{...}; nor using different names?
#include <cstdio>
class A{
public:
virtual void getSize(size_t &i) = 0;
void getSize(int &d){
size_t i;
getSize(i);
d = static_cast<int>(i);
}
};
class B : public A{
public:
void getSize(size_t &i) override{
i = 4;
}
};
int main(){
size_t t;
int i;
B b;
b.getSize(t);
b.getSize(i); // error: non-const lvalue reference to type 'size_t' (aka 'unsigned long') cannot bind to a value of unrelated type 'int'
b.A::getSize(i); // this works but is not acceptable (too much changes in production code)
printf("%zu, %d",t,i);
return 0;
}
You can choose to expose the method with a using statement:
class B : public A
{
// ...
using A::getSize;
}
In your code snippets, you have used uninitialised values in many places, this invokes UB.
I have a templated base class that I use as a pseudo-state-machine kind of object. It has a primary method Progress_State() that (after error checking) steps through an enum (provided as one of the template arguments), and runs a handler for whichever state it is in. The problem is that I have to use a this pointer to reference the Event_Handler array, which is an array of derived-class function pointers (i.e. Event_Handlers[i] = Derived_Class::*).
The function definitions were in a separate XX.cpp file that included the XX.h file (where the template classes were defined). However, since all the functions were templated functions, I was ending up with unresolved symbols. Upon some research, I discovered that the templated function definitions need to be accessible to the compiler when compiling files that use the template class, and so I've renamed the XX.cpp to an XX.tpp and put in an #include "XX.tpp" in the bottom of the "XX.h." It had compiled before without an issue, but just that change caused compile errors. Most notably, I'm getting an "expression must have pointer type" error in the line where I try and call the stored function pointer.
Templates.h
/*
* derived_class = is the derived class type, used for correctly
* using the function pointers
* event_type = the enum that we're using as "sequencer"
* max_events = the "max_XX" enum, used to set our handler array size
*/
template< derived_class, event_type, max_events >
Class Base{
// Set up the typedef for the derived class function pointer
typedef int(derived_class::*PFN)(void);
public:
// ....
int Progress_State();
// ....
private:
// ....
PFN Event_Handlers[Num_Events];
event_type Current_State;
// ....
};
// Bring in the templated function definitions
#include "Templates.tpp"
Templates.tpp
template< derived_class, event_type, max_events >
int Base::Progress_State(){
// Various error checking stuff, including whether or not we're
// at the end of the sequence, or if we have a null handler
// If no errors, continue.
// FYI: 0 indicates no errors
if( 0 == this->*Event_Handlers[Current_State]() ){ // <--* error happens here
// Step sequence -- some funkiness here to allow for incrementing
// of the sequence without overloading the ++ operator for every
// enum we intend to track, while also protecting against
// overruns
Current_State = static_cast<event_type>(
(static_cast<int>(Current_Event) + 1) % max_events
);
}
// ... do other stuff as needed ...
}
I suspect that this is happening because the "this" pointer is actually pointing to some kind of derived class, but I can't figure out a way around it.
Here are a few other things I've tried:
The following lines generate the following error:
OK == this->*Event_Handlers[Current_State]();
OK == *Event_Handlers[Current_State]();
(*this).*Event_Handlers[Current_State]();
error: "expression must have (pointer-to-) function
The expected functionality would be to just call the registered handler function (set separately) and step the sequence.
Thanks in advance
I see the following problem in your code:
You try to call a member function of a derived class inside the base class with this which is not a compatible pointer type. You have first to cast to the pointer type of the derived class. You "know" that this is a pointer of the derived class, as you are using the CRTP pattern here. https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
With a simplified example the call is something like:
template < typename Derived >
class Base
{
public:
using PTR_T = void(Derived::*)();
PTR_T ptr;
Base( PTR_T _ptr ) : ptr {_ptr}{}
void Call()
{
// the important thing here is the cast to the derived type of "this"
(((Derived*)this)->*ptr) ();
}
};
class Derived: public Base< Derived >
{
public:
void F() { std::cout << "Hello" << std::endl; }
Derived():Base{ &Derived::F } {}
};
int main()
{
Derived d;
d.Call();
}
It looks like you are searching for std::invoke. This is the functionality that MSVC used already for a while to deal with callable objects. (_INVOKE before available in the standard).
auto return value = std::invoke(func, arg1, arg2, ...);
For your case, you could call this as:
auto errorCode = std::invoke(EventHandlers[Current_State], *this);
I am building a c++ class library for embedded projects.
One concept I have is a class named Task.
Task has 2 members:
An integer id and a callback function pointer
The callbacks are created by the user and given to the constructor of the class.
I want to give the following options to the user:
The user may use functions of type void(*)(void)
The user may use function of type void (*)(unsigned int). That parameter should be the id of the task, when the callback is called.
The user may use a combination of the above function types for different tasks
The tasks also have an execute() method that calls the callback function. This method should also provide the task id as an argument, if needed
One solution would be to add a boolean member in Task called 'has_arguments' and overload the constructor to set it with regard to the type of function pointer it was given in the code.
I could also use a union for the callback member or use a void pointer and cast it to whatever suitable during execution.
The execution of the task would involve checking the 'has_arguments' member, casting the pointer to the appropriate type and calling the callback in the right way.
But is there any way to avoid this extra member and check?
I tried to always cast the function pointers to void(*)(unsigned int) and always provide the argument when I called them. And it worked.
So is it that bad to call a functions that takes no arguments, with an argument?
It worked for me, but I suppose that it is a really bad practice.
Any other ideas on what I could implement instead?
I don't want to dictate to the users to make functions with variable arguments lists. I want to leave them the freedom to use simple task agnostic functions,
or make more intelligent functions that are aware of their task ID
So is it that bad to call a functions that takes no arguments with an argument?
Yes of course!
It worked for me, but I suppose that it is a really bad practice
"It worked for me" isn't a very valid argument if your program has undefined behavior. Because it might not work for me.
Any other ideas how I could implement instead?
A tagged union is really the best way to implement this sort of thing in my opinion. You can always use boot::variant or std::variant for a safer tagged union if you can.
Really, having just one extra member (which is a bool) isn't going to destroy your performance, same for the additional branches that you will have to introduce, even on embedded. Measure first, you can then always optimize if you find that the branches are indeed bottlenecks. :)
If you cannot use std::function due to limitation of embedded platform use union and a tag, then properly set type by overloaded setter or ctor and in call use a switch on type:
struct Task {
enum CallbackType {
cbVoid,
cbId
};
using VoidCb = void(*)(void);
using IdCb = void(*)(unsigned);
int id = 0;
CallbackType type;
union {
VoidCb vcb;
IdCb idcb;
} function;
Task( VoidCb cb ) : type( cbVoid ), function( cb ) {}
Task( IdCb cb ) : type( cbId ), function( cb ) {}
void call() {
switch( type ) {
case cbVoid : function.vcb(); return;
case cbId : function.idcb( id ); return;
}
}
};
Calling a function through a function pointer that has been casted to a different type invokes undefined behaviour (cf. thins online C++ standard draft concerning casting of function pointers):
A function pointer can be explicitly converted to a function pointer
of a different type. The effect of calling a function through a
pointer to a function type ([dcl.fct]) that is not the same as the
type used in the definition of the function is undefined. Except that
converting a prvalue of type “pointer to T1” to the type “pointer to
T2” (where T1 and T2 are function types) and back to its original type
yields the original pointer value, the result of such a pointer
conversion is unspecified. [ Note: see also [conv.ptr] for more
details of pointer conversions. — end note ]
Hence, you should not use it / do it as described in your question.
A way to overcome this problem would be to enforce that correct function pointers are stored for the one and for the other case. This could be done through a discriminator / type data member and two separate function pointer members (or a union of these two separate function pointers) as described in the answer of #Slava.
Another approach could be to distinguish different task types and use inheritance and overriding to perform the callbacks correctly. Of course, this influences the way you will create / use your tasks. But maybe it solves your problem in a more extensible way than with type members and unions.
typedef void(*VoidCallbackType)(void) ;
typedef void(*IdCallbackType)(unsigned) ;
struct Task {
virtual void doCallback() = 0;
};
struct TaskWithId : Task {
unsigned id;
IdCallbackType cb;
TaskWithId(unsigned id, IdCallbackType cb) : id(id), cb(cb) { }
virtual void doCallback() {
cb(id);
}
};
struct TaskWithoutId: Task {
VoidCallbackType cb;
TaskWithoutId(VoidCallbackType cb) : cb(cb) { }
virtual void doCallback() {
cb();
}
};
You can create something under the covers that looks like the same interface. That is, auto-create helper wrapper functions that can throw away the task id if the callback doesn't want it.
class Task {
template <void (*CB)(void)> struct task_void {
static void cb (int) { CB(); }
operator Task () const { return Task(*this); }
};
template <void (*CB)(int)> struct task_int {
static void cb (int id) { CB(id); }
operator Task () const { return Task(*this); }
};
static volatile int next_id_;
int id_;
void (*cb_)(int);
template <typename CB> Task (CB) : id_(next_id_++), cb_(CB::cb) {}
public:
template <void (*CB)(void)> static Task make () { return task_void<CB>(); }
template <void (*CB)(int)> static Task make () { return task_int<CB>(); }
void execute () { cb_(id_); }
};
The private constructor is accessible to the helper templates for initialization. The helper templates can choose to hide the parameter or not.
So now, you can create a task with either kind of callback.
void cb_void () {
std::cout << __func__ << std::endl;
}
void cb_int (int id) {
std::cout << __func__ << ':' << id << std::endl;
}
//...
Task t1 = Task::make<cb_void>();
Task t2 = Task::make<cb_int>();
t1.execute();
t2.execute();
I am using a pointer of abstract type that is inherited from a base class.
Currently, each subclass must include the following behaviour in their constructor:
p = &f; //where p is the inherited pointer and f is the subclass filter
Naturally, I wish to move this behaviour up to the base class but I'm struggling to get this work. I'm not sure whether this is due how I am declaring types or if I need to change the implementation to reflect the movement of the behaviour (or something else!).
I've essentially tried to copy this line and call the base constructor through the subclass constructor:
//base.h
class Base {
pcl::Filter<pcl::PointXYZRGB>* f;
public:
Base(pcl::Filter<pcl::PointXYZRGB> abs_filter);
};
//base.cpp
Base::Base(pcl::Filter<pcl::PointXYZRGB> abs_filter) { f = &abs_filter; }
//subclass.h
class Subclass: public Base {
pcl::VoxelGrid<pcl::PointXYZRGB> vg;
public:
Subclass(void);
};
//subclass.cpp
Subclass::Subclass(void): Base(vg) { }
This will not compile and produces the following error:
error: cannot declare parameter ‘abs_filter’ to be of abstract type ‘pcl::Filter<pcl::PointXYZRGB>’
I tried to take the address pcl::Filter<pcl::PointXYZRGB> &abs_filter and change the method to f = abs_filter; but this also doesn't compile, reporting the following:
error: cannot convert ‘pcl::Filter<pcl::PointXYZRGB>’ to ‘pcl::Filter<pcl::PointXYZRGB>*’ in assignment Base::Base(pcl::Filter<pcl::PointXYZRGB> &abs_filter) { f = abs_filter; }
Where am I going wrong in what I am doing?
Any help is much appreciated!
When defining a function having a parameter passed by value, this is what happens
int myFun(myClass x) {
// x exists only in this function
// because is a copy of the argument passed to x
}
So change
Base(pcl::Filter<pcl::PointXYZRGB> abs_filter) { f = &abs_filter; }
to
Base(pcl::Filter<pcl::PointXYZRGB>& abs_filter) { f = &abs_filter; }
Not to get a copy of it, to pass the value itself.
You are setting f to a pointer to a local variable - that will not work (the abs_filter is a local copy of the vg-variable). Use one of the following:
Base::Base(pcl::Filter<pcl::PointXYZRGB>&abs_filter) { f = &abs_filter;}
Base::Base(pcl::Filter<pcl::PointXYZRGB>*abs_filter) { f = abs_filter; }
(with corresponding change in classes).
I have my fancyFunction which takes a set of elements implementing interface A. The function does a complicated analysis of those elements, based on properties read through interface A. During this analysis, it will call methods of a Consumer c which will take the elements as arguments.
The Consumer is designed to take arguments of a specific type which has absolutely nothing to do with A.
You could imagine that A is an abstraction for edges in a graph. The graph is analyzed in fancyFunction and - for example - every time the function "crosses" an edge, it will send that edge to a Consumer which prints additional information stored in the edge that has nothing to do with it being an edge.
The code given below would of course not compile in a typed language (particularly C++), but leaving out the types (Matlab, Python), the code would work.
To make it work in a typed language (particularly C++), I see two options:
Declare the function as
template <class CONSUMER>
void fancyFunction(A[] setOfAs, CONSUMER c){ ... }
Declare operation1 and operation2 to take the most general object and then do a downcast in the implementation.
What do you recommend to do in that situation? (As far as I see, the visitor pattern is NOT an option.)
Full code outline (I did not use C++ in a while, so please excuse if there are minor syntactical mistakes.):
void fancyFunction(A[] setOfAs, Consumer* c){
// do fancy analysis of setOfAs by properties
// read through interface A
double x = setOfAs[i]->getX();
// call functions in c with arguments of setOfAs[j]
...
c->operationX(setOfAs[i]);
...
c->operationY(setOfAs[j]);
...
}
class A{
virtual double getX();
}
class Consumer{
virtual void operationX(??? x); // whoops, what type do we expect?
virtual void operationY(??? y); // whoops, what type do we expect?
}
class Consumer1{
void operationX(Obj1 x){ ... } // whoops, override with different type
void operationY(Obj1 y){ ... } // whoops, override with different type
}
class Consumer2{
void operationX(Obj2 x){ ... } // whoops, override with different type
void operationY(Obj2 y){ ... } // whoops, override with different type
}
class Obj1 : public A {};
class Obj2 : public A {};
void test(){
Obj1 o1[];
Obj2 o2[];
Callback1 c1;
Callback2 c2;
fancyFunction(o1, &c1);
fancyFunction(o2, &c2);
}
I believe the solution you're looking for is called the Visitor Pattern.
You don't want to manually cast each instance of object A in your fancy function, because that is a maintenance nightmare and a clear code smell.
On the other hand, what if each object automatically handled its own casting? That's the Visitor Pattern.
You begin by defining a new "Visit" function in your base class (A), taking your Consumer as its only argument:
class A
{
public:
virtual void Visit(Consumer& consumer) = 0;
}
You then implement this function for every inherited class, thusly:
class B : public A
{
public:
void Visit(Consumer& consumer)
{
consumer.DoOperation(this); // 'this' utomatically resolves to type B*
}
}
Each derived type now handles calling the appropriate operation overload, by passing the 'this' pointer to the provided Consumer instance. The 'this' pointer is automatically interpreted as the most specific type possible.
Looking back through your original example code, it appears you have each Consumer providing multiple operations, and only handling a single type. This pattern would likely require that you change this paradigm slightly: create a single Consumer for each operation, where each consumer provides overloads for every possible inherited type.
class ConsumerX
{
public:
void DoOperation(A* a) { /* ERROR! This is a base type. If this function is called, you probably need to implement another overload. */ }
void DoOperation(B* b) { /* Much better */ }
}
class ConsumerY
{
public:
void DoOperation(A* a) { /* ERROR! This is a base type. If this function is called, you probably need to implement another overload. */ }
void DoOperation(B* b) { /* Much better */ }
}
Then your implementation loop looks something like this:
ConsumerX consumerX; // Does Operation X for every type
ConsumerY consumerY; // Does Operation Y for every type
for(int x = 0; x < numElements, x++)
{
auto element = setOfAs[x];
element.Visit(consumerX); //Do operation X
element.Visit(consumerY); //Do operation Y
}
Clearly a case where templates are appropriate. I'd even question why your fancyFunction is insisting on base class A. It should just take a begin and end iterator. I wouldn't bother with a consumer either. Make that flexible too, just take any function.
In fact, I wouldn't even write a fancyFunction. It already exists:
std::for_each(o1.begin(), o1.end(),
[c1](Obj1 o) { double x = o.getX(); c1.operationX(o); c1.operationY(o); }
);