My program is to evaluate and characterize time series information. There are about 90 distinct signals that the data may have. Each signal has a unique formula and distinct set of parameters and values. This code and my problem(s) with it is for loading these values from a config file. Compiler is VS 2010.
Each signal is represented by a class, here illustrated with the class TRI{}, and each such class derives from the class SIGNAL{}. SIGNAL contains a static map (my actual code uses unordered_map) which is to hold the pairs of signal names and pointers to the signal's member function which assigns the parameter values to their respective variables. My problem is with manipulating this member function.
Apparently, the address of the signal's member function, in this code &TRI::load_cfg_vals, is never stored in the map, sig_map. So it seems from the debugger. When I try to call the TRI signal's load function, the compiler says I'm trying to call something that's not a function. Please see the code for some of my failed attempts.
How can I get this to work with these objects? I really don't know what the problem is, and worse, I don't know what I'm not understanding about how to use STL or C++.
(I'm about ready to give up. I'm considering an alternative, more C-like approach. Using a map, associate each signal name with a unique integer (already in the actual code - they're all represented as unique single bits). Load each element of an array of void pointers with the address of the load function of the signal whose integer value is the offset into the array of that element. The first way I chose, the code below, seemed easier to maintain, a little more high-level.)
Among the many questions and answers I studied before posting this were
member function pointers and inheritance
C++ Map of string and member function pointer
C++ pointers to member functions
C++ Call pointer to member with a map from a const function
TIA
#include <iostream>
#include <map>
#include <string>
using namespace std;
typedef std::map< string, void *> ARG_MAP;
typedef ARG_MAP::iterator ARG_ITR;
typedef std::pair < ARG_ITR, bool> ARG_PAIR;
// forward decl
class SIGNAL;
typedef int (SIGNAL::*PF)(void);
typedef std::map< string, PF> SIG_MAP;
typedef SIG_MAP::iterator SIG_MAP_ITR;
typedef std::pair < SIG_MAP_ITR, bool> SIG_MAP_PAIR;
class SIGNAL
{
public:
ARG_MAP arg_map;
ARG_ITR ai;
ARG_PAIR ap;
static SIG_MAP sig_map;
SIGNAL() {};
~SIGNAL(){};
virtual int calc() = 0;
virtual int load_cfg_vals() = 0;
};
// tried globals versus members, no difference
SIG_MAP SIGNAL::sig_map;
SIG_MAP_ITR smi;
SIG_MAP_PAIR smp;
class TRI: public SIGNAL
{
public:
float f;
int calc(){return 1;}
int load_cfg_vals()
{
// the f arg
ai = arg_map.find("f_descriptive_name");
*(float *) ai->second = (float)12.005;
return 1;
};
TRI()
{
// associates the TRI class function 'load_cfg_vals()' with the
// signal name 'tri'
SIGNAL::sig_map.insert(std::make_pair ("tri",
(PF) &TRI::load_cfg_vals));
// this apparently doesn't load the address of the function, see below
//sig_map.insert(std::make_pair ("tri",&TRI::load_cfg_vals));
// fails with error C2440: 'initializing' : cannot convert from
// from 'int (__thiscall TRI::* )(void)' to 'PF '
//SIGNAL::sig_map.insert( map<string, PF>::value_type("tri",
// dynamic_cast< & SIGNAL::load_cfg_vals> (&TRI::load_cfg_vals) ));
// C2059: syntax error : '&'
// so, maybe this is right but for my lack of understanding of what
// types are involved/required here
// contains the list of descriptive names of the signal's parameters
// and the addresses of the variables that hold the parameters'values
arg_map.insert(std::make_pair ("f_descriptive_name", (void*) &f));
};
~TRI(){};
};
int main(void)
{
TRI tri;
PF pf;
char * input_str = "tri"; // this and the names of the many other
// signals would be read from the cfg file
// while there are still more signal names to read in
// while( fscanf(...input_str...) { removed
if( (smi = tri.sig_map.find (input_str)) == tri.sig_map.end())
cout << "'" << input_str << "' not found\n";
else
{
// smi->second is supposed to contain the function of the
// signal class that is to properly interpret and handle
// the list of values stored in the cfg file
//(smi->second)();
// error C2064: term does not evaluate to a function taking
// 0 arguments
string s = smi->first; // OK
pf = (PF)smi->second;
// Doesn't contain the address of the function that was
// loaded, above, in TRI(). The debugger identifies
// it as TRI::`vcall'{4}', I don't know what that is.
// Debugger emits the entire type of the operator and
// its return value, but I can't get it to format for
// proper display here. If someone wants to see it,
// I'll supply it unformatted.
//int z = (*pf)();
// error C2064: term does not evaluate to a function taking 0
// arguments
// the following don't help the value in pf. same error C2064 or
// complaints about improper use of the casts
//pf = reinterpret_cast <int (__thiscall *)(void)>(smi->second);
//pf = static_cast <int (__thiscall *)(void)>(smi->second);
}
// } // end while removed
return 1;
}