Passing the address of a function template - c++

Consider the following function:
template <int node>
void RemainingEnergyTrace (double oldValue, double newValue)
{
std::stringstream ss;
ss << "Energy_" << node << ".log";
static std::fstream f (ss.str().c_str(), std::ios::out);
f << Simulator::Now().GetSeconds() << " Remaining energy=" << newValue << std::endl;
}
Note the template definition of the function int node. I try to pass the address of this function in main():
int inc = 0;
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
which generates the following errors:
error: the value of ‘inc’ is not usable in a constant expression
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
^
error: no matching function for call to ‘MakeCallback(<unresolved overloaded function type>)’
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
^
However, the following statement works:
eSources.Get (0)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<0>));
In summary, an actual number works, but when an integer variable is passed in the template format, it does not. Is it because the integer variable has to be of const type (as suggested by the error)?
I am trying to actually run a loop and pass the address of the function for different integer values. How can I make this work?
for(int inc = 0; inc<nWifi; inc++)
{
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
}

In short, you can't. Since templates are expanded at compilation time, you need to provide the values at compilation time as well. If nWifi is a value that's only available at runtime, you need to use a regular parameter:
void RemainingEnergyTrace (double oldValue, double newValue, int node);
If you want then to create partially applied functions to pass to your MakeCallback, you can create them using lambdas:
for(int inc = 0; inc<nWifi; inc++)
{
auto callback = [=](double oldVal, double newVal) {
RemainingEnergyTrace(oldVal, newVal, inc);
};
...
}
But this won't decay to a function pointer, so you might need to change your MakeCallback API to e.g. use std::function (which is a preferred method nowadays) or to take an additional parameter1, or alternatively use some library that will provide the delegate functionality you need.
1Typically, a C or C++ API that takes function pointers would also take an additional void* parameter to store alongside the function pointer. Then, when calling, the pointer would be passed to that function, and store the necessary closure data (in your case, it could point to the inc value residing somewhere in memory). Without knowing how the MakeCallback works, it's impossible to tell what would be the best solution here.

Related

Calling map function (Indirection requires pointer operand) [duplicate]

I'm trying to make a table of function pointers within a class. I haven't been able to find any examples of this online, most involve using member function pointers outside of their class.
for example:
class Test
{
typedef void (Test::*FunctionType)();
FunctionType table[0x100];
void TestFunc()
{
}
void FillTable()
{
for(int i = 0; i < 0x100; i++)
table[i] = &Test::TestFunc;
}
void Execute(int which)
{
table[which]();
}
}test;
Gives me the error "term does not evaluate to a function taking 0 arguments".
In this line in the Execute function:
table[which]();
You can't call it like that because it's not a normal function. You have to provide it with an object on which to operate, because it's a pointer to a member function, not a pointer to a function (there's a difference):
(this->*table[which])();
That will make the invoking object whichever object is pointed to by the this pointer (the one that's executing Execute).
Also, when posting errors, make sure to include the line on which the error occurs.
Seth has the right answer. Next time, look up the compiler error number on MSDN and you'll see the same: Compiler Error C2064.
You need a context in which to call your function. In your case, the context is this:
void Execute(int which)
{
(this->*table[which])();
}

ESP was not properly saved across a function call when using function pointers

I am trying to create a program which saves the function pointer of a member function to an array. The program then takes the function pointer from that array and calls the function said pointer points to. This works as long as the member function used does not have any arguments. When I give it arguments the following error occurs in Visual Studio 2017:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
My code is:
typedef uint8_t byte;
template<typename T>
class Test
{
public:
void FuncTest(byte* data)
{
cout << (T)(0.0625f) << endl;
}
};
typedef Test<float> fTest;
typedef Test<long long> lTest;
int main()
{
byte data[1024];
{
void (fTest::*ffp)(byte*) = &fTest::FuncTest;
//void (lTest::*lfp)(byte*) = &lTest::FuncTest;
printf("%p\n", ffp);
memcpy(&data[0], (int64*)&ffp, sizeof(int64));
}
{
int64 pData;
memcpy(&pData, &data[0], sizeof(int64));
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
printf("%p\n", pData);
func_pointer(nullptr);
}
}
If anyone could help, it would be greatly appreciated.
Ignoring the storage in an array your code is essentially:
void (Test::*ffp)(byte*) = &fTest::FuncTest;
void* pData = (void*)ffp;
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
func_pointer(nullptr);
The type of ffp is essentially (although not exactly due to differing calling conventions) void (fTest*, byte*) which doesn't match the type of func_pointer.
The solution to this is to use std::function with with either std::bind or lambdas to convert the function signatures. e.g.:
std::vector<std::function<void(byte*)>> functions;
fTest test;
functions.push_back([=](byte* data){ test.FuncTest(data); });
functions.front()(nullptr);

c++ save class templated function pointer inside map

I'm having a small problem which I can't wrap my head around.
I have a function that looks like this:
template <typename T>
std::unique_ptr<Environment>& CreateEnvironment(sf::Vector2f& _position, bool _addToStatic = false);
This is my function pointer typedef
typedef std::unique_ptr<Environment>& (WorldEditor::*CreateEnvironmentPtr)(sf::Vector2f&, bool);
std::map<std::string,CreateEnvironmentPtr> listEnv;
And I'm trying to simply do this:
listEnv["test"] = &CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
And i get the following error:
error C2440: '=' : cannot convert from 'std::unique_ptr<_Ty> *' to
'std::unique_ptr<_Ty> &(__thiscall WorldEditor::* )(sf::Vector2f
&,bool)'
I understand what the error is saying, but I don't know how to solve it. Also why does it even care about the return type when I'm pointing to the address of the function?
Best regards
nilo
problems such as these are often much better solved with std::function
std::map<std::string, std::function<void()> listEnv;
listEnv.emplace("test", [] {
CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
});
to call:
listEnv.at("test")->second();
Based on your post I am not sure if you are attempting to create the member function pointer and map inside the CreateEnvironment class or outside of it, so I'll solve what I think is the more difficult problem of pointer to a separate object's member function.
I simplified your classes like so:
Environment
struct Environment
{
int i = 1;
};
Coin
struct Coin
{
int k = 0;
};
WorldEditor
struct WorldEditor
{
template <typename T>
std::unique_ptr<Environment> CreateEnvironment(int& _j, bool _addToStatic = false)
{
return std::make_unique<Environment>();
}
};
Solution: Map an object's member fn pointer, and then call it later
(I will be using C++11/14 syntax in my answer)
//declare a pointer to member function in WorldEditor
using CreateEnvironmentPtr = std::unique_ptr<Environment> (WorldEditor::*)(int&, bool);
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to the CreateEnvironment<Coin> function
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = &WorldEditor::CreateEnvironment<Coin>;
// call the member function pointer using the instance I created, as well as
// the mapped function
(myWorldEditor.*listEnv["test"])(myInt, false);
// (printing member value to cout to show it worked)
std::cout << (myWorldEditor.*listEnv["test"])(myInt, false)->i << std::endl; // prints 1
Live Demo
Solution 2: use std::bind and std::function
Perhaps we already know the parameters to the member function call at the time we create the entry for map. Using std::bind with a std::function will help us achieve that (Similar to Richard Hodges' solution):
// now our "function pointer" is really just a std::function that takes no arguments
using CreateEnvironmentPtr = std::function<std::unique_ptr<Environment>(void)>;
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to that function pointer
//ensure it gets called with the right args
// by using std::bind (which will also make the arg list appear the be void at call time)
// note that std::bind needs an instance of the class immediately after
// listing the function it should be binding
// only afterwards will we then pass the int& and bool
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = std::bind(&WorldEditor::CreateEnvironment<Coin>, &myWorldEditor, myInt, false);
// the mapped function
listEnv["test"]()->i;
// (printing resulting unique_ptr<Environment>'s member to cout to show it worked)
std::cout << listEnv["test"]()->i << std::endl; // prints 1
Live Demo 2

C++ pointers to member functions

I'd like to use a pointer to member function in C++, but it doesn't work:
pointer declaration:
int (MY_NAMESPACE::Number::*parse_function)(string, int);
pointer assignation:
parse_function = &MY_NAMESPACE::Number::parse_number;
This call works perfectly (itd is an iterator to elements of a map):
printf("%s\t%p\n",itd->first.c_str(),itd->second.parse_function);
But this one doesn't work:
int ret = (itd->second.*parse_function)(str, pts);
$ error: 'parse_function' was not declared in this scope
And this one neither
int ret = (itd->second.*(MY_NAMESPACE::Number::parse_function))(str, pts);
$ [location of declaration]: error: invalid use of non-static data member 'MY_NAMESPACE::Number::parse_function'
$ [location of the call]: error: from this location
I don't understant why ...
Thx in advance !!
int (MY_NAMESPACE::Number::*parse_function)(string, int);
This shows, parse_function is a pointer to a member function of class Number.
This call works perfectly (itd is an iterator to elements of a map):
printf("%s\t%p\n",itd->first.c_str(),itd->second.parse_function);
and from this we can see parse_function is a member of itd->second, whatever this is.
For this call
int ret = (itd->second.*parse_function)(str, pts);
or this call
int ret = (itd->second.*(MY_NAMESPACE::Number::parse_function))(str, pts);
to succeed, itd->second must be of type Number, which it presumably isn't. And parse_function must be defined as either a variable in the current or enclosing scope (fist case) or a static variable of class Number (second case).
So you need some Number and apply parse_function to that
Number num;
(num.*(itd->second.parse_function))(str, pts);
or with a pointer
Number *pnum;
(pnum->*(itd->second.parse_function))(str, pts);
Update:
Since itd->second is a Number, you must apply parse_function, which is a member of it, like this
int ret = (itd->second.*(itd->second.parse_function))(str, pts);
You can define pointers to functions like so: type(*variable)() = &function;
For example:
int(*func_ptr)();
func_ptr = &myFunction;
I might just not realize your code this early morning, but problem could be that parse_function is a pointer, yet you're calling it like itd->second.*parse_function.
Pointers are called with the ->*, so try doing itd->second->parse_function.
Might not fix anything tho, I can't really seem to catch onto your code.
Posting more information, it's hard to tell from two lines of code.
Here's one example on how it's used in actual code, this one calls func() through cb() using pointers and parameters only:
int func()
{
cout << "Hello" << endl;
return 0;
}
void cb(int(*f)())
{
f();
}
int main()
{
int(*f)() = &func;
cb(f);
return 0;
}

Function template

I have a function template as this.
template<class T> T getFromString(const string& inStream)
{
istringstream stream (inStream);
T t;
stream >> t;
return t;
}
I am not getting how to use this function template. I have tried the usual method of using function template it was giving an error. Please let me know for getting out of this.
You can use it like this:
std::string a = "11";
int n = getFromString<int>(a);
This will extract the integer value from the string.
BTW, it is good to use T t = T(); inside the template as it will gurantee the initialization for the basic datatypes even if the extaction fails.
Unleashing the power of Boost:
int n = boost::lexical_cast<int>("11");
The problem is that the compiler cannot use the return type to infer the types of the function. You need to explicitly provide the type that you want as part of the function call, as #Naveen already mentioned: getFromString<int>("123"). Another approach is changing the function signature so that instead of returning it receives the type as an argument:
template <typename T>
void getFromString( const std::string & str, T & value ) { ... }
int main() {
int x;
getFromString("123",x);
}
As you provide a variable of type T in the call, the compiler is now able to infer the type from the arguments. (x is an int, so you are calling getFromString<int>). The disadvantage is that you need to create the variable in advance and user code will be more convoluted for simple use cases as int n = getFromString<int>( "123" );