compile error about template deduction on c++ - c++

#include <iostream>
template <int N>
class X {
public:
using I = int;
void f(I i) {
std::cout << "i: " << i << std::endl;
}
};
template <int N>
void fppm(void (X<N>::*p)(typename X<N>::I)) {
p(0);
}
int main() {
fppm(&X<33>::f);
return 0;
}
I just don't understand the compile error message of the code.
error: called object type 'void (X<33>::*)(typename X<33>::I)' is not a function or function pointer
p(0);
I think p is a function which returns void and takes int as its argument. But apparently, it's not. Could somebody give me clue?

Since p is a pointer to a nonstatic member function, you need an instance to call it with. Thus, first instantiate an object of X<33> in main:
int main() {
X<33> x;
fppm(x, &X<33>::f); // <-- Signature changed below to accept an instance
Then in your function, change the code to accept an instance of X<N> and call the member function for it:
template <int N>
void fppm(X<N> instance, void (X<N>::*p)(typename X<N>::I)) {
(instance.*p)(0);
}
The syntax may look ugly but the low precedence of the pointer to member operator requires the need for the parentheses.

As denoted in the comments already, p is a pointer to member function, but you call it like a static function (p(0);). You need a concrete object to call p on:
X<N> x;
(x.*p)(0);
// or:
X<N>* xx = new X<N>();
(xx->*p)(0);
delete xx;
Be aware that the .*/->* operators have lower precedence than the function call operator, thus you need the parentheses.
Side note: Above is for better illustration, modern C++ might use auto keyword and smart pointers instead, which could look like this:
auto x = std::make_unique<X<N>>();
(x.get()->*p)(0);

Related

Passing a math function as method's input parameter C++

I am trying to write a general integral function and I would like to implement it in such a way so that it can accept any mathematical function. That is, I would like to pass the math function as an input parameter. In pseudo-code: simpson_int(x*x). I've heard of the function template in <functional> but I don't really have experience with templates in C++.
There are some solutions that comes in my mind (and this is my approach at the problem, for sure there are more solution, and maybe what I'm pointing out is not the best), that consider the fact that you need to call the argument function more than once in the Simpson implementation (thus you need a "callable" argument):
Function pointer
Function pointers (more C than C++), where you declare with two arguments: the first one will be the pointer to a function with the specified types, while the second is the argument for your function. Lets
make an example:
#include <iostream>
double power2(double x) {
return x * x;
}
double simspon(double (*f)(double), double x) {
return f(x);
}
int main() {
std::cout << simspon(power2, 2);
return 0;
}
In this case I have used no templates for reaching the result. But this will not take any function as first argument, but only a function that has as argument a double and returns a double.
I think that most of c++ programmer will suggest you to avoid this method.
Function pointer and templates
So you maybe want to expand the previous example using templates and making it more general. It is quite simple to redefine the function
to accept a template (an abstract type) that you actually specify only when you use it in your code:
#include <iostream>
double power2(double x) {
return x * x;
}
int power2int(int x) {
return x * x;
}
template <class T, class P>
P simspon(T (*f)(P), P x) {
return f(x);
}
int main() {
std::cout << simspon<double, double>(power2, 2.0);
std::cout << simspon<int, int>(power2int, 2);
return 0;
}
T and P are two templates: the first one is used for describing the returned value of the function pointer, while the second specify the argument of the function pointer, and the returned value of simpson.So when you are writing template <class T, classP> you are actually informing the compiler that that you are using T and P as placeholder for different type. You will actually declare the type that you want later on, when you will call the function in the main. This is not good code but I'm building the path to understand templates. Also, you specify the type of your argument function when you actually call simpson, with the < >.
(Disclaimer: you should consider to use template <typename T ...> instead of class. But I'm used with the old class and there are situation in which typename cannot be used, there are a lot of questions on SO that dive into this.)
Using std::function
Instead of using a function pointer as argument you may want to create a variable that stores your function to be passed as argument of simpson. This bring several advantages, because they are actually an object inside your code that have some predictable behavior in some unwanted circumstances (for example, in case of a null function pointer you have to check the pointer itself and handle it, in case of std::function if there is no callable pointer it throws std::bad_function_call error)
Here an example, and it uses again templates, as before:
#include <iostream>
#include <functional>
double power2(double x) {
return x * x;
}
int power2int(int x) {
return x * x;
}
template <class T, class P>
P simspon(std::function<T(P)> f, P x) {
return f(x);
}
int main() {
std::function<double(double)> p_power2 = power2;
std::cout << simspon<double, double>(p_power2, 2.0);
std::function<double(double)> p_power2int = power2int;
std::cout << simspon<int, int>(power2int, 2);
return 0;
}
Using lambdas
lambdas are closure and in your case (if you can use the standard C++14) can be used alongside the auto keyword to achieve quite a general behavior, without the explicit use of templates. The closure are also able to capture part/the whole context, check the reference for this.
Let's see an example, in which I create two lambdas that receive different arguments and a simpson function that is quite general (actually it is not, is the compiler that defines different functions with respect to the call that you do).
#include <iostream>
auto lambda = [](auto x) { return x * x ; };
auto lambda_2 = [] (int x) { return x + 10; };
auto simpson(auto f, auto x) {
return f(x);
}
int main() {
std::cout << simpson(lambda, 2.0);
std::cout << simpson(lambda_2, 1);
return 0;
}
You need to compile it with the -std=c++14 flag. There are tons of advise that comes in my mind to suggest you to avoid to implement your code in this way, remember that it has only some illustrative purposes (I've more than exaggerated with the auto keyword).
Function objects (the Problem class)
Maybe an improvement for your case is to write a general class for the mathematical functions to integrate and pass the object to your function. This bring several advantages: you may want to save some of the integrative result inside your function or even write the stream operator to pretty print your problem. This is the solution employed typically by mathematical libraries.
In this extremely simple case, we have a class that is a problem. When you create a new instance for this class, a std::function is passed to the constructor and stored inside the class. The instance of the class is the argument for your simpson:
#include <iostream>
#include <functional>
template <class T, class P>
class Problem {
public:
// Attributes
std::function<T(P)> _f;
// Constructor
Problem(std::function<T(P)> f) : _f(f) {};
// Making the object callable
P operator()(P x) { return _f(x); }
};
template <class T, class P>
P simspon(Problem<T, P> p, P x) {
return p(x);
}
int main() {
Problem<double, double> prb([](double x) { return x * x; });
std::cout << simspon<double, double>(prb, 2);
return 0;
}
Use std::function, like this for example:
#include <iostream> // std::cout
#include <functional> // std::function
int main()
{
std::function<double(double)> simpson_int =([](double x) { return x * x; };
std::cout << "simpson_int(4): " << simpson_int(4) << '\n';
return 0;
}
which outputs:
simpson_int(4): 16

What's the function signature of a member function?

I'm having trouble understanding function signatures and pointers.
struct myStruct
{
static void staticFunc(){};
void nonstaticFunc(){};
};
int main()
{
void (*p)(); // Pointer to function with signature void();
p = &myStruct::staticFunc; // Works fine
p = &myStruct::nonstaticFunc; // Type mismatch
}
My compiler says that the type of myStruct::nonstaticFunc() is void (myStruct::*)(), but isn't that the type of a pointer pointing to it?
I'm asking because when you create an std::function object you pass the function signature of the function you want it to point to, like:
std::function<void()> funcPtr; // Pointer to function with signature void()
not
std::function<void(*)()> funcPtr;
If I had to guess based on the pattern of void() I would say:
void myStruct::();
or
void (myStruct::)();
But this isn't right. I don't see why I should add an asterisk just because it's nonstatic as opposed to static. In other words, pointer void(* )() points to function with signature void(), and pointer void(myStruct::*)() points to function with signature what?
To me there seems to be a basic misunderstanding of what a member pointer is. For example if you have:
struct P2d {
double x, y;
};
the member pointer double P2d::*mp = &P2d::x; cannot point to the x coordinate of a specific P2d instance, it is instead a "pointer" to the name x: to get the double you will need to provide the P2d instance you're looking for... for example:
P2d p{10, 20};
printf("%.18g\n", p.*mp); // prints 10
The same applies to member functions... for example:
struct P2d {
double x, y;
double len() const {
return sqrt(x*x + y*y);
}
};
double (P2d::*f)() const = &P2d::len;
where f is not a pointer to a member function of a specific instance and it needs a this to be called with
printf("%.18g\n", (p.*f)());
f in other words is simply a "selector" of which of the const member functions of class P2d accepting no parameters and returning a double you are interested in. In this specific case (since there is only one member function compatible) such a selector could be stored using zero bits (the only possible value you can set that pointer to is &P2d::len).
Please don't feel ashamed for not understanding member pointers at first. They're indeed sort of "strange" and not many C++ programmers understand them.
To be honest they're also not really that useful: what is needed most often is instead a pointer to a method of a specific instance.
C++11 provides that with std::function wrapper and lambdas:
std::function<double()> g = [&](){ return p.len(); };
printf("%.18g\n", g()); // calls .len() on instance p
std::function<void()> funcPtr = std::bind(&myStruct::nonstaticFunc, obj);
Is how you store a member function in std::function. The member function must be called on a valid object.
If you want to delay the passing of an object until later, you can accomplish it like this:
#include <functional>
#include <iostream>
struct A {
void foo() { std::cout << "A::foo\n"; }
};
int main() {
using namespace std::placeholders;
std::function<void(A&)> f = std::bind(&A::foo, _1);
A a;
f(a);
return 0;
}
std::bind will take care of the details for you. std::function still must have the signature of a regular function as it's type parameter. But it can mask a member, if the object is made to appear as a parameter to the function.
Addenum:
For assigning into std::function, you don't even need std::bind for late binding of the object, so long as the prototype is correct:
std::function<void(A&)> f = &A::foo;
p = &myStruct::staticFunc; // Works fine
p = &myStruct::nonstaticFunc; // Type mismatch
Reason : A function-to-pointer conversion never applies to non-static member functions because an lvalue that refers to a non-static member function
cannot be obtained.
pointer void(* )() points to function with signature void(), and pointer void(myStruct::*)() points to function with signature what?
myStruct:: is to make sure that the non-static member function of struct myStruct is called (not of other structs, as shown below) :
struct myStruct
{
static void staticFunc(){};
void nonstaticFunc(){};
};
struct myStruct2
{
static void staticFunc(){};
void nonstaticFunc(){};
};
int main()
{
void (*p)(); // Pointer to function with signature void();
void (myStruct::*f)();
p = &myStruct::staticFunc; // Works fine
p = &myStruct2::staticFunc; // Works fine
f = &myStruct::nonstaticFunc; // Works fine
//f = &myStruct2::nonstaticFunc; // Error. Cannot convert 'void (myStruct2::*)()' to 'void (myStruct::*)()' in assignment
return 0;
}
When you use a pointer, std::function or std::bind to refer to a non-static member function (namely, "method" of class Foo), the first param must be a concrete object of class Foo, because non-static method must be called by a concrete object, not by Class.
More details: std::function and
std::bind.
The answer is in the doc.
Pointer to member declarator: the declaration S C::* D; declares D as
a pointer to non-static member of C of type determined by
decl-specifier-seq S.
struct C
{
void f(int n) { std::cout << n << '\n'; }
};
int main()
{
void (C::* p)(int) = &C::f; // pointer to member function f of class C
C c;
(c.*p)(1); // prints 1
C* cp = &c;
(cp->*p)(2); // prints 2
}
There are no function with signature void (). There are void (*)() for a function or void (foo::*)() for a method of foo. The asterisk is mandatory because it's a pointer to x. std::function has nothing to do with that.
Note: Your confusion is that void() is that same signature that void (*)(). Or even int() <=> int (*)(). Maybe you think that you can write int (foo::*) to have a method pointer. But this is a data member pointer because the parenthesis are optional, int (foo::*) <=> int foo::*.
To avoid such obscure syntax you need to write your pointer to function/member with the return type, the asterisk and his parameters.

C++ Function call via an object with public member pointer to function, without using dereference operator

Alright, I think the title is sufficiently descriptive (yet confusing, sorry).
I'm reading this library: Timer1.
In the header file there is a public member pointer to a function as follows:
class TimerOne
{
public:
void (*isrCallback)(); // C-style ptr to `void(void)` function
};
There exists an instantiated object of the TimerOne class, called "Timer1".
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct? I am familiar with calling functions via function pointers by using the dereference operator.
Ex:
(*myFunc)();
So I would have expected the above call via the object to be something more like:
(*Timer1.isrCallback)();
So, what are the acceptable options for calling functions via function pointers, as both stand-alone function pointers and members of an object?
See also:
[very useful!] Typedef function pointer?
Summary of the answer:
These are all valid and fine ways to call a function pointer:
myFuncPtr();
(*myFuncPtr)();
(**myFuncPtr)();
(***myFuncPtr)();
// etc.
(**********************************f)(); // also valid
Things you can do with a function pointer.
1: The first is calling the function via explicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
(*myfptr)(nValue); // call function myfunc(nValue) through myfptr.
2: The second way is via implicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
myfptr(nValue); // call function myfunc(nValue) through myfptr.
As you can see, the implicit dereference method looks just like a normal function call -- which is what you’d expect, since function are simply implicitly convertible to function pointers!!
In your code:
void foo()
{
cout << "hi" << endl;
}
class TimerOne
{
public:
void(*isrCallback)();
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &foo; //Assigning the address
//Timer1.isrCallback = foo; //We could use this statement as well, it simply proves function are simply implicitly convertible to function pointers. Just like arrays decay to pointer.
Timer1.isrCallback(); //Implicit dereference
(*Timer1.isrCallback)(); //Explicit dereference
return 0;
}
You don't have to dereference a function pointer to call it. According to the standard ([expr.call]/1),
The postfix expression shall have
function type or pointer to function type.
So (*myFunc)() is valid, and so is myFunc(). In fact, (**myFunc)() is valid too, and you can dereference as many times as you want (can you figure out why?)
You asked:
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct?
The type of Timer1.isrCallback is void (*)(). It is a pointer to a function. That's why you can use that syntax.
It is similar to using:
void foo()
{
}
void test_foo()
{
void (*fptr)() = foo;
fptr();
}
You can also use:
void test_foo()
{
void (*fptr)() = foo;
(*fptr)();
}
but the first form is equally valid.
Update, in response to comment by OP
Given the posted definition of the class you would use:
(*Timer1.isrCallback)();
To use
(Timer1.*isrCallback)();
isrCallback has to be defined as a non-member variable of whose type is a pointer to a member variable of TimerOne.
void (TimerOne::*isrCallback)();
Example:
#include <iostream>
class TimerOne
{
public:
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
void (TimerOne::*isrCallback)() = &TimerOne::foo;
(Timer1.*isrCallback)();
}
Output:
In TimerOne::foo();
(Test this code)
If you want to define isrCallbak as a member variable of TimerOne, you'll need to use:
#include <iostream>
class TimerOne
{
public:
void (TimerOne::*isrCallback)();
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &TimerOne::foo;
// A little complicated syntax.
(Timer1.*(Timer1.isrCallback))();
}
Output:
In TimerOne::foo();
(Test this code)

how to decide if bind() need parenthesis in the parameter

I am using bind() to bind a function and its parameters together. I used the build-in functor multiplies and I also tried a function I wrote myself AddVal2(). The following is a correct version of the code. But I really don't understand why std::bind(std::multiplies<int>(),std::placeholders::_1,10) has to include () with multiplies<int>, while bind(AddVal2,std::placeholders::_1,10) write AddVal2 instead of AddVal2(). Thank you.
#include<iostream>
#include<vector>
#include<algorithm>
void AddVal2(int x, int y)
{ std::cout << x+y << std::endl;}
int main()
{
std::vector<int> vec = {1,2,3,4,5};
std::vector<int> vec_result;
std::transform(vec.begin(),vec.begin()+2,std::back_inserter(vec_result),std::bind(std::multiplies<int>(),std::placeholders::_1,10));
for (std::vector<int>::iterator itr = vec_result.begin(); itr !=vec_result.end();++itr){std::cout << *itr << std::endl;}
for_each(vec.begin(),vec.end(),std::bind(AddVal2,std::placeholders::_1,10));
}
That's simple: std::multiplies<T> is a class template which defines a
function call operator. It looks something like this:
template <typename T>
struct multiplies {
// some typedefs are here, too
T operator()(T const& a0, T const& a1) const { return a0 * a1; }
};
To create such an object, you'll use a default constructor, i.e., std::multiplies<T>().
On the other hand AddVal2 is a function. To get a function object from a normal function you just mention the function and it'll decay into a function pointer. Alternatively you can also use &AddVal2 to explicitly obtain a function pointer (for member functions you have to explicitly take the address).

templates of functions

I'm told to create template of function , that will take 4 arguments :
pointer
reference
pointer to array
pointer to function
How to perform this task ? I was trying :
#include <iostream>
using namespace std;
int nothing(int a)
{
return a;
}
template<typename T> T func(int *L, int &M, char *K, int (*P)(int))
{
cout << L << "," << M << "," << K[0] << "," << P() << endl;
return 0;
}
int main()
{
int x = 3;
int *z = &x;
int &y = x;
char c[3];
int (*pf)(int) = nothing;
cout << "some result of func" << func(z, y, c, pf) << endl;
system("pause");
return 0;
}
This gives me "no matching function , I guess for 'pf'. Also now I have no control over what to pass within pf or am I wrong ?
You're almost there. However, in C++, a reference is denoted with & (not $), a pointer to an array is a pointer to its first element, and a function pointer needs additional parentheses: T (*pf)().
Note that it is called a function template (as opposed to class templates).
Edit: (You shouldn't edit your question so that answers given so far suddenly become nonsensical.)
pf(x) calls the function stored in pf. pf already is a function pointer, so pass it as it is.
(Also, in your declaration P is a function taking an X, while pf takes an int. I suppose this is an editing error?)
Note that, with function pointers, there are 1..N types involved, one result type, and 0..N argument types. "Create a function template that will take a pointer to a function" can mean any of that. Or it means
template< typename F >
void f(F func);
which can be called with any function pointer.
To help you little bit more, try to remember how the "main" function taking arguments looks like, this will help you to see how you can make a pointer to an array.
You now have some problems left...
TYPE (*P)(x) says you expect a pointer to function that takes an argument of type x - change it to an existing type.
In the expression func(z, y, c, pf(x)) you try to call the function pointer pf instead of just passing it.
Then you are calling func with parameters based on different types for the first 3 parameters, int and char, but func expects them to be based on the same type.
Try writing down with what types func will be called with and try matching that to a signature for func with TYPE being substituted to say int.
E.g. if you have the following:
template<typename T> void f(T* a, T* b);
and try to call it like this:
int* a = 0;
int* b = 0;
f(a, b);
the compiler instantiates and calls a function
void f<int>(int*, int*);
But if you do the following:
int* a = 0;
char* b = 0;
f(a, b);
what should be called?
void f<int> (int*, int* ); // doesn't match, 2nd argument is char*
void f<char>(char*, char*); // doesn't match, 1st argument is int*