Reputation: 6107
I am trying to understand the difference between function types <void()>
and function pointer types <void (*)()>
stl::function
can point to functions through <void()>
, but I seem to need to use <void (*)()>
in my own template classes:
void f1() {
std::cout << "hi!\n";
}
template<class T> struct X
{
T t;
};
int main()
{
std::function<void()> f = f1; // stl handles this, and f is callable
f(); // OK
// X<void()> x; // compilation error - a member of a class template cannot aquire a function type
X<void (*)()> x2; // OK
x2.t = f1; // OK
x2.t(); // OK
return 0;
}
Are function types such as <void()>
new to C++ 11, and introduced along with std::function
?
I have seen some other questions regarding this, but have not found an explanation which is clear to me, and searching the web for C++ function type does not yield satisfactory results.
I would greatly appreciate any clear explanation or references to one.
Upvotes: 3
Views: 212
Reputation: 153830
Function types aren’t new to C++11 at all: the existed even in C. However, you cannot have objects of function types, i.e.,
template <typename T>
struct X {
T t;
};
X<void()> does_not_work;
X<void(*)()> works;
However, you can turn a function type into a pointer type:
template <typename T>
struct X {
T* t;
};
Upon using a function differently than calling it the function decays into a function pointer. Decaying a function into a pointer is equivalent to taking the function’s address.
Of course, what std::function<...>
does is quite different anyway: it actually defines a function call operator. To do so it deckares a general template and specializes it for function types:
template <typename> class function;
template <typename R, typename... A>
class function<R(A...)> {
public:
R operator()(A...);
// ...
};
Upvotes: 6
Reputation: 36389
You can't store a function in a variable, you can only store a function pointer. What is slightly confusing is that the language automatically converts a function into a function pointer when you try to assign the function name to a variable.
Your class would have to be:
template<class T> struct X
{
T* t;
};
To make X<void()> x
work. This would of course stop X<void (*)()> x2
from working, you'd have to specialise the template for different types.
Upvotes: 3