i've got a function declaration in c++ and need to know how it's working:
template<class x>
int fun(x, x(*)(x*) );
The first arg is an object of type x. And how to describe the second one?
That is the declaration of a template function that returns an integer and takes, as parameters, an x and a pointer to a function that returns an x and takes, as a parameter, an x*.
The part x(*)(x*) is the part that means "a pointer to a function that returns an x and takes, as a parameter, an x*". The first x is the return type, the (*) indicates that it is a pointer to a function (if the parameter had a name, it would be written x(*argname)(x*)), and the third x* is just the argument.
Calling it would look like this:
int f(int* iptr) { return something; }
fun(4, f); // no need for the explicit template parameter because it can be deduced
Or more generally
template<typename x>
x functionname(x* xptr) { return something; }
It will not work in C because, as Daniel White said in a comment, C doesn't have templates.
The second parameter type, where x is a class:
x(*)(x*)
Means "a pointer (*) to a function returning x and taking x*. For example:
class MyClass {};
MyClass doit(MyClass* arg) { return *arg; }
MyClass instance;
int result = fun(instance, doit);
It is a pointer to a function that return the object of type x, and got one parameter of a pointer to the type x.
Related
void(*)(void) is a function pointer while I suppose void(void) is also a way to represent function type. It is used as template parameter in std::function <functional>
What is void(void) and how it is different from void(*)(void)?
What is void(void) and how it is different from void(*)(void)?
They are distinct types. Although the former(void(void)) can be implicitly converted to the latter(void(*)(void)) in many contexts.
The type void(void) is called a function type. The following are also function types:
int (int, int) //this is a function type
void(int) //this is a function type as well
On the other hand, void (*)(void) is a pointer to a function type. That is, it is a pointer that points to a function with 0 parameters and return type of void.
TL;DR
The void(void) is a specification of a function type, it's
signature.
The void(*)(void) is a pointer to function.
These are distinct.
First, let's start by saying, that sometimes the void(void) will be automatically treated as a pointer to function (i.e. in a parameter list). We still can be explicit and use the void(*)(void), but the void(void) will be an equivalent in these cases.
// Here, we explicitly state that the f is a pointer to function
void foo(void (*f)(void), int i);
// Equivalent, f is automatically treated as a pointer to the function
void foo(void f(void), int i);
This will not be the case for the mentioned std::function for example. The types of the two are different, yet may have similar behavior (i.e. we can use the function call operator on a pointer to function).
void bar();
// Prints 1
std::cout << std::is_same<void(void), decltype(bar)>::value << '\n';
// Prints 1 as well
// Note the pointer type specifier
std::cout << std::is_same<void(*)(void), decltype(bar)*>::value << '\n';
// Prints 0
// Note the absence of the pointer type specifier
std::cout << std::is_same<void(*)(void), decltype(bar)>::value << '\n';
And particularly:
// Ok
std::function<decltype(bar)> fn1 = bar;
// error: variable ‘std::function<void (*)()> fn2’ has initializer but incomplete type
std::function<decltype(bar)*> fn2 = bar;
Note, that we can however "store" a pointer to a member function in std::function, but even then the template's parameter still won't be of a pointer to function type, but a plain function signature.
struct MyType {
void func(int) {}
};
int main() {
// Note, we can't have a member function without an instance of the type
// Thus we specify the usually implicit first param and the explicit int param
std::function<void(MyType&, int)> fn_mem = &MyType::func;
MyType my_object;
fn_mem(my_object, 21);
}
For more on std::function please refer to the reference. In short, the use of the std::function instead of the function pointers has the same moto as using the smart pointers instead of the raw pointers.
You may wonder on other uses of the void(void) or int(int) style function type specifications, so here's another example you may see often:
using func_t = int(int);
// func_ptr_func return a pointer to the func_t type alias
func_t* func_ptr_func();
N.B. unlike in the case of a parameter, the compiler won't treat the function type in a return as a pointer to function type. Thus, we must explicitly specify the pointer type in case of the return.
// Here, baz is a function that doesn't take any agruments
// And returns a pointer to a function that takes an int argument and "returns" void
void (*baz())(int);
for void fun(){}, std::is_same_v<void(void)>, decltype(fun)> is true; and std::is_same_v<void(*)(void)>, decltype(&fun)> is true. In fact, those are their real types. However, the standard approve you convert an object that has type void(void) to void(*)(void) implicitly (so you can even write (******funptr)()), that's why we always confuse them.
I know void (*)(int) is to function pointer but what is void(int)?
It's used for std::function template.
Say I have a function void fun(int){} : decltype(&fun) gives void(*)(int) but decltype(fun) gives void(int)
If T is a type, then T* denotes the type "pointer-to-T".
The type void(int) is a function type, it's the type of a function taking one int and returning void. For example, it is the type of f if f is declared as void f(int);
If T = void(int), then T* is spelled void(*)(int), so the latter is the type of a function pointer. You can also form a reference to a function, which is T& = void(&)(int); this is occasionally more useful (e.g. you can take the address of a function lvalue).
Aside note: Function lvalues decay to their function pointer very easily. You can call a function either via a function lvalue or via a function pointer. When used as an operand for the indirection operator (*), the function value decays, so you can dereference the pointer again and again:
printf("Hello world\n"); // OK
(*printf)("Hello world\n"); // also OK
(****printf)("Hello world\n"); // four-star programmer
Some of the only times that a function does not decay is when used as the operand of the address-of operator, or when bound to a reference:
void f(int); // our example function
void(*p1)(int) = &f; // no decay of "f" here
void(*p2)(int) = f; // "f" decays
void(&r1)(int) = f; // no decay of "f" here
void g(void(&callback)(int), int n) {
callback(n);
}
g(f, 10); // no decay of "f" here
template <typename F, typename ...Args>
decltype(auto) h(F&& callback, Args&&... args) {
return std::forward<F>(callback)(std::forward<Args>(args)...);
}
h(f, 10); // no decay of "f" here
void (*whatever)(int)
should be read as: whatever is a pointer, pointing to a function, that accepts one int as argument, and returns nothing (ie., void).
void whatever(int)
should be read as: whatever is a function (NOT a pointer), that accepts one int as argument, and returns nothing (ie., void)
Once the pointer to a function is initialized to point to a valid function (one that satisfies the prototype), then you can invoke the function either through its "real" name, or through the pointer.
Pointers to functions are very useful - they're variables, just like anything else, so you can pass them around to other functions (see e.g. qsort()), you can put them in structs, etc..
Given this, the following code is valid:
#include <stdio.h>
void myfun(int x) {
printf("The value of X is %d\n", x);
}
int main() {
void (*myfunp)(int);
myfunp = &myfun;
myfun(13);
myfunp(12);
return 0;
}
void(*)(int) should be read as type of a pointer which is pointing to a function, that accepts one int as argument, and returns nothing.
For understanding more on function to pointer and its usage please check here: http://www.cprogramming.com/tutorial/function-pointers.html
I met this code:
auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
in the previous code, we can apply the address operator to a member function while there is no instance
object been created, how can that be possible?
The type system of C++ contains a lesser-known category of types which are pointers to members. Given any class type C and any object or function type T, there is a pointer-to-member type T C::*. Values of these types can be obtained by applying the address-of operator to the qualified name of a class member. For example:
struct Foo;
int Foo::* pi; // C = Foo, T = int
void (Foo::* pf)(bool, int); // C = Foo, T = void(bool, int)
struct Foo {
int a;
int b;
void f(bool, int);
void g(bool, int);
};
pi = &Foo::a;
pf = &Foo::f;
The member pointer itself only selects a class member abstractly, unrelated to any class instance. To actually use the pointer, you need a class instance, and the member-dereference operator .*:
Foo x;
int n = x.*pi; // gets x.a
(x.*pf)(true, n); // calls x.f(true, n)
pf = &Foo::g;
(x.*pf)(true, n); // calls x.g(true, n)
(The parentheses in the call expression through the pointer-to-member pf are necessary because otherwise the expression a.*b(c) means a.*(b(c)). This is occasionally a point of confusion for new users.)
Don't confuse a pointer-to-member to an object member with a pointer to the actual object!
int * p = &(x.*pi); // p = &x.a
Here p points to the actual int subobject x.a and is an ordinary object pointer, whereas pi is a pointer-to-member that abstractly selects the Foo::a member of a Foo object.
Taking the address of Foo's member function gives you a pointer to member function. This type is completely independent of any Foo object. If you're going to actually call the function, you need to provide a Foo object. In this case, the this parameter of Foo::print_sum is being bound to &foo with std::bind.
of course you need to have an instance of type Foo called foo, because the member function Foo::print_sum is bound to foo .
I was looking at the emulated version of nullptr and saw this converting operator (a member of nullptr_t):
template<class C, class T> // or any type of null
operator T C::*() const // member pointer...
{ return 0; }
This syntax for pointer to member function confuses me. I usually expect to see such a type as something like
R (C::*)(I1, I2, ...)
With the template above, there's no input arguments. I can't figure out how the type deduction works in this case. I'm having trouble forming a specific question, other than, how does this work? If I have code like this:
typedef int (MyClass::*MyTypedef)(float);
MyTypedef m = nullptr;
I'm guessing T deduces to int, and C deduces to MyClass. What "happens" to float?
That is a pointer to member, not necessarily a pointer to member function. The difference is that it can generate a pointer to member function or a pointer to non-function member.
Now in the particular use case, the destination is a pointer to member, the compiler is seeing an expression in which it needs a int (MyClass::*)(float), and on the other hand it has a nullptr. It tries to find a conversion and it finds the operator T C::*(), which is a valid conversion if C is deduced to be MyClass and T is deduced to be int (float) [function taking a float and returning an int].
I also find this particular corner of the language a bit confusing (having typedefs, or deduced types for functions), for example this is legal if weird:
typedef void int_f(int);
struct X {
int_f m;
};
void X::m(int x) { std::cout << x << '\n'; }
The same thing is going on in the conversion operator that you are concerned with.
Consider a template class like:
template<typename ReturnType, ReturnType Fn()>
class Proxy
{
void run()
{
ReturnType ret = Fn();
// ... do something ...
}
};
// and a functions
int fn1() { return 5; }
float fn2() { return 5; }
This can be instantiated by using:
Proxy<int, &fn1> p1;
But explicitly declaring the return value type seems needless. What I am trying to achieve is something like:
someProxyInstantation<&fn1> p1;
someProxyInstantation<&fn2> p2;
Unfortunately, I'm no c++ expect and this seems like a hidden corner of the language (at least for me).
If I could just get from the pointer to the function to its type - something like:
std::tr1::result_of<&fn>::type // Error 1 error C2923: 'std::tr1::result_of' : 'fn1' is not a valid template type argument for parameter '_Fty'
the error makes sense since the parameter is not a "type" at all
C++0x has the decltype(&fn1) but that is years away.
Any way of doing this in C++03 (+ tr1)?
Restrictions:
- I don't want to pass the functor, f1 and f2 have to remain global functions that have a return value (can't move it to parameter).)
This isn't possible in C++03. If you want to pass a function pointer as a non-type parameter, the compiler has to know the type of the parameter. So you have to provide the missing pieces (in this case, the return type). You can give the proxy the function pointer as a value at runtime, and provide it with the type of it as the only argument. Then you could write a generator function for you that does this job:
template<typename T>
Proxy<T> make_proxy(T t) { return Proxy<T>(t); }
Sadly, in current C++, you still have to give it the type in order to assign to a automatic variable:
Proxy<int(*)()> p = make_proxy(&fn1);
You can't use auto p = make_proxy(&fn1); yet. Note that if you want to use a function type on the left side, you have to change the generator function to provide not a function pointer type:
template<typename T>
Proxy<typename boost::remove_pointer<T>::type> make_proxy(T t) {
return Proxy<typename boost::remove_pointer<T>::type>(t);
}
Now you can do
Proxy<int()> p = make_proxy(&fn1);
using the proxy, you can now just do
doSomething(make_proxy(&fn1));
And if doSomething is templated or otherwise polymorphic, it will not require you to know the exact type of the function.