473,378 Members | 1,507 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Functor Question - part II

Apologies for the length of this message, but I'm having problems
getting an alternate function to be executed via a functor
implementation.

I have two classes (BkgLand and BkgWater) that comprise a portion of a
much larger simulation. These classes exist in separate libraries
although the library that class BkgWater is in links in the library
containing the BkgLand class (sounds confusing I know). In the
simulation architecture that I'm using to implement these classes, the
Land based classes will be instantiated by default and the functors
will be registered for those classes. If the Water class objects are
present within the system I build (i.e. I've built an executable
containing the Water class), then the Water based classes will be
instantiated after the Land classes and those water functors are then
registered (and should take precedence).

When I test the simulation for a Land configuration I see that the
Land based functors execute just fine (and the Water objects aren't
present). When I configure the simulation for a 'Water case', I see
the message that the Land functors are being registered and then the
Water functors are being registered (as I expected), but when the
'Call_m' function is called (from the "Land" side of the simulation),
I get a segmentation fault. I checked for null pointers, but didn't
see evidence of that.

I don't know if :
- I've declared the funcTable arrays correctly and in the
appropriate sections of code (I had several compilation errors prior
to using the approach outlined below).
- There are some kind of scope issues
- Something between the two libraries is missing to allow the
land based side of the program to interpret the registered water
functions.

It almost seems as if the program doesn't know which function really
should be getting used (specFunc_0 from land or from water) when the
Call_m function is invoked for the water configuration.

Something to note, the programming guidelines I was given constrained
me to not compiling / linking libWater.so with the land based code,
only vice-versa is allowed.

Any suggestions would be greatly appreciated. Alf was already a big
help in an earlier question I posted on a related topic. Please see
the following code snippets. I will be glad to provide more
information if needed.

Danny
#ifndef TFUNCTOR_H
#define TFUNCTOR_H

#include "my_config.h"
#include "Struct1.h"
#include "Struct2.h"

BEGIN_MY_NAMESPACE

class TFunctor
{
public:

virtual void Call_m(STRUCT1*, STRUCT2*)=0;
};
END_MY_NAMESPACE

#endif //TFUNCTOR_H

#ifndef SPECFUNCTOR_H
#define SPECFUNCTOR_H

#include "my_config.h"
#include "TFunctor.h"

BEGIN_MY_NAMESPACE

template <class TClassclass TSpecificFunctor : public TFunctor
{
public:

// Constructor - takes pointer to an object and pointer to
// a member function and stores them in two private variables
TSpecificFunctor( TClass* _pt2Object, void(TClass::*tfpt)
(STRUCT1*, STRUCT2*) )
{ pt2Object = _pt2Object; fpt = tfpt; };

// override function "call" in base class
virtual void Call_m(STRUCT1* bkgnd, STRUCT2* geo)
{ (*pt2Object.*fpt) (bkgnd, geo);

private:
void (TClass::*fpt) (STRUCT1*, STRUCT2*);
};
END_MY_NAMESPACE

#endif //SPECFUNCTOR_H

#ifndef BKGLAND_H
#define BKGLAND_H

#include "my_config.h"

#include "Struct1.h"
#include "Struct2.h"

BEGIN_MY_NAMESPACE

class BkgLand
{
public:

// Constructor/Destructor
BkgLand() {};
virtual ~BkgLand() {};

void Initialize();
void Update();

TFunctor::TFunctor *funcTable[];
};

END_MY_NAMESPACE

#endif // BKGLAND_H
BKGLAND.cpp Code (compiled in library LIBGround.so):

#include "BkgLand.h"
#Include "SpecFunctor.h"
#include "LandScats.h"

void BkgLand::Initialize( )

cout << "REGISTER LAND FUNCTIONS" << endl;

// init_test function is a public member of the LandScats class
LandScats objLand;
TSpecificFunctor<LandScatsspecFunc_0(&objLand,
&LandScats::init_test);
TFunctor::TFunctor *funcTable[] = { &specFunc_0 };
}

void BkgLand::Update()
{
//geom* and bkgndscat* are provided to this class via accessor
methods.

// Call appropriate registered function (can be land or water
based)
funcTable[0]->Call_m(bkgndscat, geom);
}

BKGWATER.cpp Code (compiled in a separate library, LIBWater.so, but
LIBGround is linked in when this library is built):

#include "BkgWater.h"
#include "TFunctor.h"
#include "SpecFunctor.h"
#include "WaterScats.h"

void BkgWater::Initialize()
{
cout << "REGISTER WATER FUNCTIONS" << endl;

// init_test function is a public member of the WaterScats
class
WaterScats objWater;
TSpecificFunctor<WaterScatsspecFunc_0( &objWater,
&WaterScats::init_test);
TFunctor::TFunctor *funcTable[] = { &specFunc_0 };
}

#ifndef BKGWATER_H
#define BKGWATER_H

#include "Tfunctor.h"

BEGIN_MY_NAMESPACE
class BkgWater
{
BkgWater();
virtual ~BkgWater();

public:
virtual void Initialize();
TFunctor::TFunctor *funcTable[];

}
END_MY_NAMESPACE
#endif // BKGWATER_H

Nov 11 '07 #1
4 1360
On Nov 11, 6:38 pm, BSand0...@msn.com wrote:

[...]
There are several obvious errors in the code you posted. But
it's not the actual code, since it won't compile. (And you
really should strip out the namespace management macros junk
before posting. It may be necessary in your environment, but it
just causes confusion here.)
class TFunctor
{
public:
virtual void Call_m(STRUCT1*, STRUCT2*)=0;
};
template <class TClassclass TSpecificFunctor : public TFunctor
{
public:

// Constructor - takes pointer to an object and pointer to
// a member function and stores them in two private variables
TSpecificFunctor( TClass* _pt2Object, void(TClass::*tfpt)
(STRUCT1*, STRUCT2*) )
{ pt2Object = _pt2Object; fpt = tfpt; };
Where is pt2Object declared? What is its type (presumably
TClass*, but it could be a base class pointer, or even void*)?
// override function "call" in base class
virtual void Call_m(STRUCT1* bkgnd, STRUCT2* geo)
{ (*pt2Object.*fpt) (bkgnd, geo);
If pt2Object is a pointer, this statement isn't legal, and
shouldn't compile. If pt2Object is a TClass*, then what you
probably want is:

{ (pt2Object->*fpt)( bkgnd, geo ) ; }

Putting an additional parentheses around *pt2Object would also
work.
private:
void (TClass::*fpt) (STRUCT1*, STRUCT2*);
};
class BkgLand
{
public:

// Constructor/Destructor
BkgLand() {};
virtual ~BkgLand() {};

void Initialize();
void Update();
TFunctor::TFunctor *funcTable[];
Why TFunctor::TFunctor, instead of just TFunctor? I think it's
legal (because of type injection), but it is very confusing to
the reader, and I seem to recall encountering some compilers
which didn't accept it. (On seeing the name TFunctor after
TFunctor::, the compiler treated it as the "name" of a
constructor).

This won't compile anyway, of course, since you have to specify
the dimensions of a (non-static) member table.
};
void BkgLand::Initialize( )
cout << "REGISTER LAND FUNCTIONS" << endl;
// init_test function is a public member of the LandScats class
LandScats objLand;
TSpecificFunctor<LandScatsspecFunc_0(&objLand,
&LandScats::init_test);
TFunctor::TFunctor *funcTable[] = { &specFunc_0 };
The above statement is a no-op. You define a local table of
pointers to TFunctor (again, same comment as above concerning
the name), with a dimension of 1, and initialize it with the
address of a local variable. You then immeately leave the
function, causing both the table and the local variable to
cease to exist. (Of course, the TSpecificFunctor instance
contains a pointer to still another local variable, and so
wouldn't be usable outside of the function anyway.
}
void BkgLand::Update()
{
//geom* and bkgndscat* are provided to this class via accessor
methods.
// Call appropriate registered function (can be land or water
based)
funcTable[0]->Call_m(bkgndscat, geom);
Here, of course, you use the funcTable variable of the object.
Since you've never initialized the contents of the table,
however, you've got totally undefined behavior.
}
BKGWATER.cpp Code (compiled in a separate library,
LIBWater.so, but LIBGround is linked in when this library is
built):
Has all of the problems of BKGLAND.cpp, so I won't bother
commenting.

Since your code won't compile, it's rather irrelevant to talk
about what it does on execution. If you want help with a
specific symptom, then you really should post the actual code
which causes that symptom. Otherwise, we really can't help you
much.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Nov 12 '07 #2
On Mon, 12 Nov 2007 09:00:17 +0000, James Kanze wrote:
On Nov 11, 6:38 pm, BSand0...@msn.com wrote:
[snip]
> // override function "call" in base class virtual void
Call_m(STRUCT1* bkgnd, STRUCT2* geo) { (*pt2Object.*fpt) (bkgnd,
geo);

If pt2Object is a pointer, this statement isn't legal, and shouldn't
compile. If pt2Object is a TClass*, then what you probably want is:

{ (pt2Object->*fpt)( bkgnd, geo ) ; }

Putting an additional parentheses around *pt2Object would also work.
Surprisingly it should compile - .* and ->* operators have lower
precedence than dereference operator (*). But of course relying on this
makes no sense and operator ->* is appropriate here. I remember this
precedence only because it's so counter-intuitive.

[snip]
> // Call appropriate registered function (can be land or water
based)
funcTable[0]->Call_m(bkgndscat, geom);

Here, of course, you use the funcTable variable of the object. Since
you've never initialized the contents of the table, however, you've got
totally undefined behavior.
I couldn't see its definition so I would expect linker error.
--
Tadeusz B. Kopec (tk****@NOSPAMPLEASElife.pl)
When in panic, fear and doubt,
Drink in barrels, eat, and shout.
Nov 12 '07 #3
On Nov 12, 10:18 pm, "Tadeusz B. Kopec" <tko...@NOSPAMPLEASElife.pl>
wrote:
On Mon, 12 Nov 2007 09:00:17 +0000, James Kanze wrote:
On Nov 11, 6:38 pm, BSand0...@msn.com wrote:
[snip]
// override function "call" in base class virtual void
Call_m(STRUCT1* bkgnd, STRUCT2* geo) { (*pt2Object.*fpt) (bkgnd,
geo);
If pt2Object is a pointer, this statement isn't legal, and shouldn't
compile. If pt2Object is a TClass*, then what you probably want is:
{ (pt2Object->*fpt)( bkgnd, geo ) ; }
Putting an additional parentheses around *pt2Object would also work.
Surprisingly it should compile - .* and ->* operators have lower
precedence than dereference operator (*). But of course relying on this
makes no sense and operator ->* is appropriate here. I remember this
precedence only because it's so counter-intuitive.
You're right.

I'll admit that I don't bother memorizing anything but the
"obvious" precedences: */ before +-, unary before binary, and
post-fix before pre-fix, and logical operators and comparisons
after everything else. Interestingly enough, this case is
actually covered by those rules: .* is a binary operator. But
I'm so used to the binding of . and -that it didn't occur to
that .* and ->* would be different. (It's one of those things
that are obvious... once they've been pointed out to you.)
[snip]
// Call appropriate registered function (can be land or water
based)
funcTable[0]->Call_m(bkgndscat, geom);
Here, of course, you use the funcTable variable of the object. Since
you've never initialized the contents of the table, however, you've got
totally undefined behavior.
I couldn't see its definition so I would expect linker error.
It was defined as a non-static member of the class. The problem
is that he didn't give a dimension, so the definition wouldn't
be legal, and the compiler should have complained.

If it were a static member, of course, then the declaration in
the class is not a definition, so the type doesn't have to be
complete, and he can use a simple []. But then, as you say, he
needs a definition somewhere or the linker should complain.

The real problem, of course, is that he's not posting the real
code (at least judging from the symptoms he described).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 13 '07 #4
On Tue, 13 Nov 2007 09:45:13 +0000, James Kanze wrote:
[snip]
It was defined as a non-static member of the class. The problem is that
he didn't give a dimension, so the definition wouldn't be legal, and the
compiler should have complained.
It must this funny property of human brain - I saw what I thought it
should be not what it really was. I saw no dimension, I knew definition
needs a dimension so I saw 'static' there. :-)
BTW: my gcc 4.1.3 needs -pedantic to complain about zero-sized arrays.
--
Tadeusz B. Kopec (tk****@NOSPAMPLEASElife.pl)
Any excuse will serve a tyrant.
-- Aesop
Nov 13 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Sean | last post by:
#include <iostream> #include <algorithm> struct functor { ~functor() {std::cout << 'D';} void operator()(int a) {std::cout << a;} }; int main() { int a = {1,2,3,4,5}; functor f;
6
by: Gert Van den Eynde | last post by:
Hi all, I'm struggling a bit with Functors generated for an ABC. This is the functor code: class Functor{ public: virtual double operator(double x)=0 }
3
by: CoolPint | last post by:
I have implemented a generic priority queue below and tested it works fine, but I have one small problem I cannot understand. I have type parameter F which determines the priority so that users can...
8
by: Amit | last post by:
Hello all. If I want to use an object both as a Functor and also, if I pass a function pointer, how can it be done ? For instance, I have something like this template< typename Iter, typename...
8
by: daniel.w.gelder | last post by:
Hello, I have been trying to write a functor template for a week now and I'm just having tons of trouble because I don't understand an issue that I guess is pretty basic to this task. ...
4
by: daniel.w.gelder | last post by:
I wrote a template class that takes a function prototype and lets you store and call a C-level function, like this: inline string SampleFunction(int, bool) {..} functor<string (int, bool)>...
12
by: aaragon | last post by:
Hi everyone, I'm trying to provide some external functionality to a class through a functor object defined by the user. The concept is as follows: template <class Functor> class ClassA {...
2
by: Lionel B | last post by:
I have a function which takes a functor argument. I which to call it for a functor which is actually a class member; this works fine, using the mem_fun_ref and bind1st functions (see listing 1...
5
by: Fei Liu | last post by:
Hello, I have a situation where I need to design a library for multi-thread application, each thread does some work in a client supplied std::ptr_fun(free_function) or a functor. Now since it's...
2
by: aaragon | last post by:
Hi guys, Is there a way to return a functor from a recursive call that takes different paths? Let's say that I have a tree structure like: root | first child ---- nextSibling ----nextSibling...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.