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*
Related
Here I declared two template classes: A and B, B derives from A:
template<typename T>
class A {
public:
int a;
T t;
};
template<typename T>
class B : public A<T> {
public:
int b;
};
And I make a shared_ptr<B<T>> and assign it to shared_ptr<A<T>>, it's ok:
auto b = std::make_shared<B<std::string>>();
std::shared_ptr<A<std::string>> a = b;
Here I declared a template function accept shared_ptr A<T>:
template<typename T>
void proc(std::shared_ptr<A<T>> &a) {
std::cout << a->a << std::endl;
}
it accepts a as argument, but rejects b:
proc<std::string>(a); // OK
proc<std::string>(b); // template argument deduction/substitution failed
// cannot convert 'b' (type 'std::shared_ptr<B<std::__cxx11::basic_string<char> > >') to type 'std::shared_ptr<A<std::__cxx11::basic_string<char> > >&'
I use g++ as compiler with -std=c++11.
This error brings me a lot problems and how could I fix this elegantly?
Given proc<std::string>(b);, b needs to be converted to std::shared_ptr<A<std::string>>. That means a temporary std::shared_ptr<A<std::string>> will be constructed and then passed to proc. The parameter type of proc is an lvalue-reference to non-const, i.e. std::shared_ptr<A<T>> &, which can't bind to temporaries.
You can change the parameter type to lvalue-reference to const, which could bind to temporaries. e.g.
template<typename T>
void proc(const std::shared_ptr<A<T>> &a) {
// ^^^^^
std::cout << a->a << std::endl;
}
First of all, you make a shared_ptr called:
auto b = std::make_shared<B<std::string>>();
Is of type std::shared_ptr<B<std::string>> and,
std::shared_ptr<A<std::string>> a = b;
Is of type std::shared_ptr<A<std::string>>...
In your function parameter, however, you have:
void proc(std::shared_ptr<A<T>> &a)
Which only points to the shared_ptr of A, not B, so it is obvious that B won't become A...
The solution would be to remove the lvalue reference of a from the function definition, like:
void proc(std::shared_ptr<A<T>> a)
so, it doesn't refer to A, and B can easily be converted to A during function call...
Edit: Added an explanation...
Explanation:
Remember pointers? from C... yes, they do the same function of references:
// Compilable both in C and C++...
int add(int a, int b, int * more_than_3) {
int const result = a + b;
if (result > 3)
*more_than_3 = 1;
return result;
}
Yeah, these which would the function of pseudo-return types in C. Like:
// Compilable both in C and C++...
int main(void) {
int more_3;
int const res = add(2, 3, &more_3);
printf("Sum of 2 + 3 is %i\n", res);
if (more_3)
printf("Given two numbers' sum is more than 3");
}
Here, an extra argument is passed which takes the address of a variable (References also do the same thing, they share their address with the variable with whom they are referenced...)
Remember, references and pointers store the address of another variable inside of them...
This might be the reason why they made the address of operator (&) also act for references in C++...
Also, unneeded, but the answer which was posted here by #songyuanyao worked, because:
void proc(std::shared_ptr<A<T>> const &a)
uses a constant reference, a reference to a constant expression, not a variable, so it didn't matter if they mismatched (A and B)
#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);
I am trying to pass a member function as argument using pointer-to-member-function. I have already seen some links like this here but I could not solve the problem.
The class Foo has two member functions. I need to pass the addition function as an argument to the NewOper function.
This is my code. I can correctly use pointer to call the addition function but it gives me an error when I try to pass it as an argument to NewOper function. I appreciate it if you tell me how I can fix it. (The last two lines cause error)
#include <iostream>
using namespace std;
class Foo{
public:
int addition(int a, int b)
{
return (a + b);
}
int NewOper(int x, int y, int(*fnc2call)(int, int))
{
int r;
r = (*fnc2call)(x, y);
return (r);
}
};
int main()
{
int m,n, k, l;
int (Foo::*fptr) (int, int) = &Foo::addition;
Foo obj;
m=(obj.*fptr)(1,2);
Foo* p = &obj;
n=(p->*fptr)(3,4);
cout << m << endl;
cout << n << endl;
//**********************
int (Foo::*fptr) (int, int, int(*fnc2call)) = &Foo::NewOper;
k = (obj.*fptr)(1, 2, addition);
}
You already have answer in your own code:
int (Foo::*fptr) (int, int) = &Foo::addition - here you correctly declared fptr as pointer to function, which is (non static) member of class Foo
But you forgot to do the same in you NewOper function definition:
int NewOper(int x, int y, int(*fnc2call)(int, int)) - this function wants address of free function as 3rd argument. Redefine it in the same way you declared fptr. But then you'll need to pass also pointer to an object of class Foo to this function
Alternatively, you can make your function addition function static as Jarod42 suggested (actually, the way it is written now, there is no reason for it to be member of class Foo unless you have further plan on it). Then you'll need to remove Foo:: from fptr definition
I'm reading a lot about "typedef functions", but I getting casting errors when I try to call this one. What's the correct syntax to call this function?
typedef ::com::Type* Func(const char* c, int i);
that statement makes Func a type. Then you'll have to say Func *f = anotherFunc given another func is defined as : ::com::Type* anotherFunc(const char *c, int i){ /*body*/ }
Then you can call f("hello", 0) and it should work.
There's no function in your code. There's only a type name Func that stands for function type. There's nothing to call there.
The name Func, as defined in your question, can be used in several different ways.
For example, you can use it to declare a function
Func foo;
The above is equivalent to declaring
::com::Type* foo(const char*, int);
This will also work for member function declarations. (However, you can't use it to define a function).
For another example, you can use it when declaring a pointer to a function, by adding an explicit *
Func *ptr = &some_other_function;
The above is equivalent to declaring
::com::Type* (*ptr)(const char*, int) = &some_other_function;
For yet another example, you can use it as a parameter type in another function
void bar(Func foo)
in which case the function type will automatically decay to function pointer type, meaning that the above declaration of bar is equivalent to
void bar(Func *foo)
and equivalent to
void bar(::com::Type* (*foo)(const char*, int));
And so on.
In other words, show us what your are trying to do with it. As is your question is too broad to be answered specifically.
typedef function syntax:
#include <iostream>
using namespace std;
int add(int a, int b) {return a+b;}
typedef int(*F)(int a, int b);
int main() {
F f = add;
cout << f(1,2) << endl;
return 0;
}
The break down of typedef int(*F)(int a, int b);
The type name is F in brackets
Return type is the int at the beginning.
The parameters are (int, int)
Usage F f = &add;:
F is our type.
f is the variable name.
add is the function with the correct signature.
A valid syntax in your case would be: typedef ::com::Type (*Func)(const char* c, int i);
Reference: [33.11] Can I convert a pointer-to-function to a void*?
#include "stdafx.h"
#include <iostream>
int f(char x, int y) { return x; }
int g(char x, int y) { return y; }
typedef int(*FunctPtr)(char,int);
int callit(FunctPtr p, char x, int y) // original
{
return p(x, y);
}
int callitB(FunctPtr p, char x, int y) // updated
{
return (*p)(x, y);
}
int _tmain(int argc, _TCHAR* argv[])
{
FunctPtr p = g; // original
std::cout << p('c', 'a') << std::endl;
FunctPtr pB = &g; // updated
std::cout << (*pB)('c', 'a') << std::endl;
return 0;
}
Question> Which way, the original or updated, is the recommended method?
I have tested both methods with VS2010 and each prints the correct result.
Thank you
Although I do see the following usage in the original post:
void baz()
{
FredMemFn p = &Fred::f; ← declare a member-function pointer
...
}
Dereferencing a function pointer yields another function pointer. So, just f(), otherwise you're only obfuscating your code.
Pointers to members are different beasts altogether. They require usage of .* or ->* operators. That's also why you should use std::function (or boost::function) instead of raw pointers to functions/memebers.
Both are okay:
p();
(*p)();
But the first one is preferable, because it is more consistent with functor object. For example, you can write a function template as:
template<typename Functor>
void f(Functor fun)
{
fun(); //uniform invocation - it doesn't matter what it is.
}
Now this can be called with function pointers, and functor object, both, which has been made possible only because I have used the first syntax.
The moral of story is : strive for uniform invocation. Write code in such a way that invocation syntax should be same irrespective of whether the invocation-entity is a function pointer or function object.
The standard allows all of the forms you use, but unless you want to
confuse readers, it's generally best to be explicit: &f to take the
address of the function, and (*p)( x, y ) to call it.
You can use either form, but it looks most natural (to me) to use this:
p(x, y);