I have seen the following (C++):
typedef n *(m)(const n*, const n*);
What does it mean and how can it be used?
I understand this:
typedef n (*myFunctP)(const n*, const n*);
but what is the difference to the typedef above?
(Hope this is no duplicate, did not find something similar...)
I asked geordi to win me some rep:
<tomalak> << TYPE_DESC<m>; struct n {}; typedef n *(m)(const n*, const n*);
<geordi> function taking 2 pointers to constant ns and returning a pointer to a n
C type declaration syntax is horrible and it does become particularly apparent when you start doing complex declarations like this. Notice how the return type and arguments are written around the m, not the n, which is totally backwards to intuition since it's m that you're creating.
Your second example is:
<tomalak> << TYPE_DESC<m>; struct n {}; typedef n (*m)(const n*, const n*);
<geordi> pointer to a function taking 2 pointers to constant ns and returning a n
By moving the *, you are no longer applying it to the function type's return type, but to the function type itself.
In C++11, unless you have a desperate need for your calls to be hyper-efficient, please stick to the following, for the love of Cthulhu! :-)
typedef std::function<n*(const n*, const n*)> m;
If you wish to stick to function pointers then you can:
using m = n*(const n*, const n*);
Prior to that you can use boost::function or learn the horrific C declarator rules. It is true that you should know them; it's just that hopefully you won't have to use them too often.
The first typedef creates an alias for a function which takes 2 parameters and returns a pointer-to-n.
The second typedef creates an alias for a pointer-to-function which takes 2 parameters and returns an n by value.
In the first case the typedef defines an alias for a function type that has two parameters of type const n *and return type n *
In the second case instead of the function type there is a declaration of a function pointer having return type n.
In the first case you could write also for example
typedef n * ( (m)(const n*, const n*) );
It is equivalent to your typedef.
As for the usage you can use it as a function declaration. For exmaple
m MyFunc;
Another example
struct A
{
typedef int n;
typedef n ( Operation )( n, n ) const;
Operation Add;
Operation Subtract;
Operation Division;
Operation Multiply;
};
// and below the function definitions
Related
I would like to understand why do i have to add an asterisk before each identifier when declaring more pointers with the same datatype on the same row.
Here is where i read from
Another thing that may call your attention is the line:
int * p1, * p2;
This declares the two pointers used in the previous example. But notice that there is an asterisk (*) for each pointer, in order for both to have type int* (pointer to int). This is required due to the precedence rules. Note that if, instead, the code was:
int * p1, p2;
p1 would indeed be of type int*, but p2 would be of type int. Spaces do not matter at all for this purpose. But anyway, simply remembering to put one asterisk per pointer is enough for most pointer users interested in declaring multiple pointers per statement. Or even better: use a different statement for each variable.
The operator precedence
The question: What rule is used here, what precedence is this? It is about comma or asterisk? I can't figure it out.
There is no any precedence rule. The gramma of a simple declaration looks like
decl-specifier-seq init-declarator-listopt ;
The sign * belongs to declarators not to decl-specidier-seq as for example type specifier int.
So you may for example rewrite the declaration
int * p1, * p2;
like
int ( * p1 ), ( * p2 );
where ( *p1 ) and ( *p2 ) are decalartors (thouhg in this case the parentheses are redundant)
You may not write for example
( int * ) p1, p2;
The compiler will issue an error.
Parentheses are required when a more complicated type is declared. For example let's declare a pointer to an array
int ( *p )[N];
where N is some constant.
So you may enclose declarators in parentheses.
Let's consider a more complicated declaration: of a function that returns a pointer to function and has as a parameter another function
void ( *f( int cmp( const void *, const void * ) )( int *a );
As for the precedence then rules of building declarators describe them in the gramma
For example
if you will write
int * a[10];
then it is an array of 10 elements of the type int *.
However if you will write
int ( *a[10] );
then its an array of 10 pointers to objects of the type int.
If you will write
int ( *a )[10];
then it is a pointer to an array of 10 integers.
Take into account that typedef is also a decl-specifier.
So for example this typedef
typedef int *intPtr;
you may rewrite like
int typedef *intPtr;
or even like
int typedef ( *intPtr );
One more example of declaration. Let's consider a multidimensional array. In can be declared like
int ( ( ( a )[N1] )[N2] );
though again the parentheses are redundant. However they can help to understand how arrays are implicitly converted to pointers to their first elements in expressions.
For example if you have an array
int a[N1][N2];
then to get a pointer declaration to its first element you can rewrite the declaration ,like
int ( a[N1] )[N2];
and now substitute a[N1] for *a (or for example *p).
int ( *p )[N2] = a;
There is not a precedence rule per se; rather, it is a rule that says that the int part applies to all the variables whereas the * only applies to the one right after it.
The general version of the rule is that all the specifiers in the declaration apply to every entity being declared. Specifiers include keywords like constexpr and static, as well as keywords that denote types like int and user-defined type names. The operators like * and & that modify the type specifiers to create more complex types, however, only apply to one entity at a time.
There's no operator precedence involved here. In fact there are no operators either. Operators operate on expressions, but this is a declaration.
The syntax for declarations is that:
T D1, D2, D3, D4;
means the same as:
T D1; T D2; T D3; T D4;
where:
T is declaration-specifier: no symbols, only keywords (e.g. int, const, static) and/or typedef-names.
Dn is a declarator, that is, an identifier (the name of the variable) perhaps with *, [] or (parameter-list) or grouping parentheses attached in various ways.
In your first example T is int, and the declarators are *p1 and *p2 .
I understand that similar questions with answers have been asked before. I already understand the concept of a function pointer and the meaning of its declaration. Following is my sample code of a function's pointer, where I assign the function pointer fp_GetBiggerElement to point to the function GetBiggerElement
#include <iostream>
typedef int (*fp_GetBiggerElement) (int, int);
// ^ ^ ^
// return type type name arguments
using namespace std;
int GetBiggerElement(int arg1, int arg2)
{
int bigger = arg1 > arg2 ? arg1 : arg2;
return bigger;
}
int main()
{
fp_GetBiggerElement funcPtr = GetBiggerElement;
int valueReturned = funcPtr(10, 20);
cout << valueReturned << endl;
return 0;
}
What I understand is, typedef means to assing a new definition for a type. Usually, the typedef statement needs two-parts(or say two-arguments)
first part is the type which needs a new alias
second part is a new alias name
typedef unsigned int UnsignedInt;
// ^ ^
// (original type) (Alias)
for example, in the code above, the first part is unsigned int and the second part is UnsignedInt
typedef char * CharPtr;
// ^ ^
// (original type) (Alias)
similarly, in the second example above, the first part is char* and the second part is CharPtr
QUESTION: I am confused with the FORMAT of the typedef statement for a function pointer. In the statement typedef int(*fp_GetBiggerElement)(int, int);, the typical two-arguments format for typedef is not followed then, how is it working?
UPDATE: I am aware that C++11 offers another way of declaring function pointer i.e. (by using statment). In this question, I am only interested to understand the syntax of typedef statement for a fucntion pointer.
I think the best idea to think about typedef syntax is like declaring variable of type you want to typedef. For example:
char *CharPtr;// declare CharPtr to be variable of type char*
typedef char *CharPtr_t;// declare CharPtr_t to be alias of type char*
Similarly with function pointers:
int (*fp) (int, int);// declare fp as pointer to int(int, int)
typedef int (*fp_t)(int, int);// declare fp_t to be alias of pointer to int(int, int)
Btw, in C++11 and further you get not-so-confusing (and more powerful) alternative to typedef - using. You should be using (pun intended) it instead. Just look:
using fp = int (*)(int, int);// declare fp_t to be alias of pointer to int(int, int)
typedef uses the same syntax as a variable declaration, but declares a type name rather than a variable name.
The parts are "intermingled" in a somewhat peculiar (some would call it "wtf?") way - a variable declaration has the same form as its use, which simplifies the parser and enables reusing code in the compiler.
It makes more sense if you read in a more "old-school" way:
int *p;
"*p is an int"
(Equivalent translation: "p is a pointer to int")
int *p, x;
"*p and x are both ints"
("p is a pointer to int, and x is an int")
int (*q)[3];
"*q is an array of three ints", or "(*q)[x] is an int"
("q is a pointer to an array of three ints")
int (*fp)(int,int);
"*fp is a function that takes two ints and returns an int"
("fp is a pointer to a function that takes two ints and returns an int")
int (*(*foo)())[3];
"*(*foo)() is an array of three ints" (alternatively, "(*(*foo)())[x] is an int) - or, in other words,
"(*foo)() is a pointer to an array of three ints" - or, in other words,
"foo is a pointer to a function that takes no arguments and returns a pointer to an array of three ints"
A slightly unreadable effect of this is that
int *p, x, (*q)[3], (*fp)(int,int), (*(*foo)())[3];
declares all of the above at once.
That's just the syntax for function pointers.
You would see the same thing if you just declare a variable.
int foo; // Normal
int (*bar)(int, int); // bar is of type int(*)(int,int)
Personally i prefer to use using = ... which in my opinion is more clear.
using fp_GetBiggerElement = int (*)(int,int);
This syntax comes from the C-way of reading variables.
Ever wondered why we need an asterisk, for every pointer we want to declare in a single expression?
int *p1, *p2, p3; // p3 is not a pointer
C++ people generally tend to see a variable having a specific type, which can be a pointer (in other words, they see the pointer characteristics as property of the type). That's why they usually prefer writing
int* p1; // notice asterisk grouped with type
C people rather read as: I have a variable p1, and if I dereference it, I get type int (so p1 being a pointer is deduced information, i. e. they see the pointer characteristics rather as property of the variable; and that's why they rather group the asterisk to the name: int *p1;).
Pretty similar for function pointers:
int (*fp) (int, int);
I have a variable fp, and if I dereference it, I get int (int, int). Same pattern then for the typedef. On the other hand, the (new) C++ way for defining an alias reflects much better the C++ way of thinking:
using fp = int (*)(int, int);
I have a variable, and it's type is a pointer (to whatever) right from the start – well, not fully consistently, though: With C++ way of thinking, function pointers might rather look like int(int, int)* or maybe requiring parentheses (int(int, int))*, but OK, that's not the way it is (wanting to stay compatible with C being reason for).
typedef declarations are similar to simple declarations but instead of declaring an identifier of a derclarator as an identifier of an object or a function they declare an identifier of a declarator as an alias for the specified type.
Consider the following examples of simple declarations
int x;
unsigned int a[10][20];
int unsigned ( *p )[10][20];
void ( *f )( int, int );
double h( double );
They declare several objects and the function h.
Now place in these declarations decl-specifier typedef (in any order relative to other decl-specifiers) and you will get that the declared identifiers become aliases of types.
typedef int x;
unsigned typedef int a[10][20];
int unsigned typedef ( *p )[10][20];
void typedef ( *f )( int, int );
typedef double h( double );
That is x is an alias of the type int. a is an alias for the type unsigned int [10][20]. p is an alias for the pointer type unsigned int ( * )[10][20]. f is an alias for the function pointer void ( * )( int, int ). And h in an alias for the function type double( double ).
What does the following template do in C++?
template <class R, class T>
struct my_type<R(*)(T)> { typedef T type; };
Specifically, what does the * stand for in this context?
In this context it makes the template specialization refer to a pointer to a function, which is declared to accept a single argument of type T, and return a value of type R. The specialization extracts the argument type and makes it available as a typedef.
Example (demo):
#include <iostream>
#include <type_traits>
int foo(float);
template <typename T>
struct my_type;
template <class R, class T>
struct my_type<R(*)(T)> { typedef T type; };
int main() {
std::cout
<< std::is_same<
float,
typename my_type<decltype(&foo)>::type
>::value
<< "\n";
return 0;
}
This outputs 1 because float and typename my_type<decltype(&foo)>::type both refer to the same type -- decltype(&foo) is the type int (*)(float), which matches the specialization R(*)(T).
Great answer above by cdhowie, but I feel it's more explaining what template specialization does, and not so much answers the specific question: what does the * stand for in R(*)(T).
For that, we need to take a look at how we specify types in C++'s type system. Don't be offended if you already know most or all this, but I think I can best explain it if I just start with the basics. If not you, perhaps someone else can learn from this (I myself was pretty confused by C(++)'s type system, coming from Pascal :)). If you just want the answer, it's the last sentence of this post.
Say we want to declare a variable named foo that is of type int.
int foo;
Well, that's easy enough. Now, let's change that to be an array of 3 ints:
int foo[3];
It's important to realize what we've done here. You might be tempted to think that array specifiers simply go last, but that's not the case. Because, to declare an array of something, we need to add brackets right after the identifier that names our variable, or foo in this case. This becomes clear when you want to extend this declaration to be an array of 2 × int[3]:
int foo[2][3];
So, by substituting foo with foo[2] in the declaration int foo[3], we get to int foo[2][3]. And that's why foo is an array of 2 × [array of 3 × int]. This becomes more apparent when we add parentheses (which we are in fact allowed to do):
int foo; // [int]
int (foo[3]); // array of 3×[int]
int ((foo[2])[3]); // array of 2×[array of 3×[int]]
C++ uses a similar system for pointers. To declare a pointer to something, prefix the identifier with a *.
int foo; // [int]
int (*foo); // pointer to [int] (same as: int *foo)
int (*(*foo)); // pointer to [pointer to [int]] (same as: int **foo)
So, we've substituted foo with (*foo) on every next line.
This is where things get interesting. We need to prefix the identifier with a * for a pointer, and postfix it with [] for an array, but then, what does int *foo[3] mean? As it turns out, int *foo[3] is parsed as int *(foo[3]). So, it is an array of 3 × [pointer to int]. To get a pointer to [array of 3 × int], we need to do: int (*foo)[3]
int *(foo[3]); // array of 3×[pointer to [int]] (same as: int *foo[3])
int (*foo)[3]; // pointer to [array of 3×[int]]
Now, to answer your question, we need to look at function declarations. This is actually similar to arrays. To declare a function, add parentheses and a list of arguments right after the identifier:
int foo; // [int]
int (foo()); // function returning [int] (same as: int foo())
Now we can also apply above rules:
int foo; // [int]
int (foo()); // function returning [int] (same as: int foo())
int ((*foo)()); // pointer to [function returning [int]] (same as: int (*foo)())
int ((*(foo[2]))()); // array of 2×[pointer to [function returning [int]]] (same as: int (*foo[2])())
To name a type without the identifier, simply erase the identifier. So the type of the third foo in above example is simply int(*)(). Note that the parentheses here are mandatory. If it were int*(), it would be a function returning [pointer to [int]].
Tip: to figure out the type of something, use a bottom-up approach, starting at the identifier (or where the identifier would be), working outward, using the following annotations: * stands for "pointer to...", [] for "array of..." and (x) for "function taking (x) and returning...". As a rule of thumb: if there are no parentheses, the right hand side goes before the left hand side.
Now we can answers your question: the * in R(*)(T) stands for: a pointer to a function that takes a T as argument and returns an R.
I'm using QVector to hold pointers to Objects, say FYPE*, in my program.
class TYPE {
// ....
};
const TYPE *ptrToCst;
QVector<TYPE*> qtVct;
// ...
if (qtVct.contains(ptrToCst)) { // Error!!!
// ....
}
The compiler says QVector::contains expects TYPE* instead of const TYPE* as its parameter. A const_cast operation would solve this problem. But it doesn't make any sense to me, since the contains method should never change what the pointer points to. And the equivalent code using STL vector works as expected.
std::vector<TYPE*> stlVct;
// ...
if (std::find(stlVct.begin(), stlVct.end(), ptrToCst)) { // Ok
// ...
}
What's the reason for this difference? Did STL treat containers that hold pointers specially, so that std::find accept pointer to const object? I guess partial template specialization was involved?
This is actually a quite interesting question about const-correctness and some non-intuitive errors, but the compiler is right in rejecting the code.
Why does is not work in Qt?
The compiler rejects the code because it would break const-correctness of the code. I don't know the library, but I think I can safely assume that the signature of contains is QVector<T>::contains( T const & value )[1], which in the case of T == type* means:
QVector<type *>::contains( type * const & value )
Now the problem is that you are trying to pass a variable of type type const *. The problem at this point is that the compiler does not know what contains does internally, only the promises it offers in it's interface. contains promises not to change the pointer, but says nothing about the pointee. There is nothing in the signature inhibiting the implementation of contains from modifying the value. Consider this similar example:
void f( int * const & p ) { // I promise not to change p
*p = 5; // ... but I can modify *p
}
int main() {
const int k = 10;
int const * p = &k;
f( p ); // Same problem as above: if allowed, f can modify k!!!
}
Why does it allow the similar call to std::find then?
The difference with std::find is that find is a template where the different argument type have a very loose coupling. The standard library does not perform type checking on the interface, but rather on the implementation of the template. If the argument is not of the proper type, it will be picked up while instantiating the template.
What this means is that the implementation will be something similar to:
template <typename Iterator, typename T>
Iterator find( Iterator start, Iterator end, T const & value ) {
while ( start != end && *start != value )
++start;
return start;
}
The type of the iterators and the value are completely unrelated, there is no constraint there other than those imposed by the code inside the template. That means that the call will match the arguments as Iterator == std::vector<type*>::iterator and T = type const *, and the signature will match. Because internally value is only used to compare with *start, and the comparison of type * and type const * const is valid (it will convert the former to the later and then compare [2]) the code compiles perfectly.
If the template had the extra restriction that the type of the second argument was Iterator::value_type const & (this could be implemented with SFINAE) then find would fail to compile with the same error.
[1] Note the choice of ordering in the declaration: type const *, rather than const type *. They are exactly the same for the compiler (and the experienced eye), but by always adding the const to the right it makes it trivial to identify what is being defined as const, and to identify that const T & with T == type * in the argument of contains is not const type *&.
[2] In the same way that you cannot bind a type * const & to a type const *, you cannot do the equivalent with pointers, type * const * cannot be converted from type const *, but if const is added to both the pointer and the pointee types, then the conversion is fine as it guarantees not to break const correctness. That conversion (which is safe) is performed in the comparison of type * == type const * const, where the left hand side gets two extra const: type const * const. If it is not clear why this does not break const-correctness, drop a comment and I will provide some code here.
Explicit template instantiation is done for concrete types, and you can be certain standard library vendor had no idea you'd write TYPE. That aside, the difference is in signatures. std::find is a free function template, something like:
template <typename I, typename T>
find(I first, I last, T value)
So, when you call it, compiler generates find(std::vector<TYPE*>::iterator, std::vector<TYPE*>::iterator, const TYPE*). Since all find does is comparisons, and you can compare const T* and T* with no problems, all is good and fluffy.
QVector<TYPE*>::contains, on the other hand, is a member function, in a class template. So it signature contains the type used to instantiate the template:
contains(TYPE*)
And therein lies the problem, because you try to call it with const TYPE* — and conversion of const T* to T* is illegal.
Also: find returns an iterator, not a boolean. Your condition should be if (std::find(...) != that_vector.end()).
To directly answer "Why QVector::contains expects pointer to non-const TYPE as its parameter": because you told it to, with the template argument.
I'm learning how to dynamically load DLL's but what I don't understand is this line
typedef void (*FunctionFunc)();
I have a few questions. If someone is able to answer them I would be grateful.
Why is typedef used?
The syntax looks odd; after void should there not be a function name or something? It looks like an anonymous function.
Is a function pointer created to store the memory address of a function?
So I'm confused at the moment; can you clarify things for me?
typedef is a language construct that associates a name to a type.
You use it the same way you would use the original type, for instance
typedef int myinteger;
typedef char *mystring;
typedef void (*myfunc)();
using them like
myinteger i; // is equivalent to int i;
mystring s; // is the same as char *s;
myfunc f; // compile equally as void (*f)();
As you can see, you could just replace the typedefed name with its definition given above.
The difficulty lies in the pointer to functions syntax and readability in C and C++, and the typedef can improve the readability of such declarations. However, the syntax is appropriate, since functions - unlike other simpler types - may have a return value and parameters, thus the sometimes lengthy and complex declaration of a pointer to function.
The readability may start to be really tricky with pointers to functions arrays, and some other even more indirect flavors.
To answer your three questions
Why is typedef used?
To ease the reading of the code - especially for pointers to functions, or structure names.
The syntax looks odd (in the pointer to function declaration)
That syntax is not obvious to read, at least when beginning. Using a typedef declaration instead eases the reading
Is a function pointer created to store the memory address of a function?
Yes, a function pointer stores the address of a function. This has nothing to do with the typedef construct which only ease the writing/reading of a program ; the compiler just expands the typedef definition before compiling the actual code.
Example:
typedef int (*t_somefunc)(int,int);
int product(int u, int v) {
return u*v;
}
t_somefunc afunc = &product;
...
int x2 = (*afunc)(123, 456); // call product() to calculate 123*456
typedef is used to alias types; in this case you're aliasing FunctionFunc to void(*)().
Indeed the syntax does look odd, have a look at this:
typedef void (*FunctionFunc) ( );
// ^ ^ ^
// return type type name arguments
No, this simply tells the compiler that the FunctionFunc type will be a function pointer, it doesn't define one, like this:
FunctionFunc x;
void doSomething() { printf("Hello there\n"); }
x = &doSomething;
x(); //prints "Hello there"
Without the typedef word, in C++ the declaration would declare a variable FunctionFunc of type pointer to function of no arguments, returning void.
With the typedef it instead defines FunctionFunc as a name for that type.
If you can use C++11 you may want to use std::function and using keyword.
using FunctionFunc = std::function<void(int arg1, std::string arg2)>;
#include <stdio.h>
#include <math.h>
/*
To define a new type name with typedef, follow these steps:
1. Write the statement as if a variable of the desired type were being declared.
2. Where the name of the declared variable would normally appear, substitute the new type name.
3. In front of everything, place the keyword typedef.
*/
// typedef a primitive data type
typedef double distance;
// typedef struct
typedef struct{
int x;
int y;
} point;
//typedef an array
typedef point points[100];
points ps = {0}; // ps is an array of 100 point
// typedef a function
typedef distance (*distanceFun_p)(point,point) ; // TYPE_DEF distanceFun_p TO BE int (*distanceFun_p)(point,point)
// prototype a function
distance findDistance(point, point);
int main(int argc, char const *argv[])
{
// delcare a function pointer
distanceFun_p func_p;
// initialize the function pointer with a function address
func_p = findDistance;
// initialize two point variables
point p1 = {0,0} , p2 = {1,1};
// call the function through the pointer
distance d = func_p(p1,p2);
printf("the distance is %f\n", d );
return 0;
}
distance findDistance(point p1, point p2)
{
distance xdiff = p1.x - p2.x;
distance ydiff = p1.y - p2.y;
return sqrt( (xdiff * xdiff) + (ydiff * ydiff) );
}
For general case of syntax you can look at annex A of the ANSI C standard.
In the Backus-Naur form from there, you can see that typedef has the type storage-class-specifier.
In the type declaration-specifiers you can see that you can mix many specifier types, the order of which does not matter.
For example, it is correct to say,
long typedef long a;
to define the type a as an alias for long long. So , to understand the typedef on the exhaustive use you need to consult some backus-naur form that defines the syntax (there are many correct grammars for ANSI C, not only that of ISO).
When you use typedef to define an alias for a function type you need to put the alias in the same place where you put the identifier of the function. In your case you define the type FunctionFunc as an alias for a pointer to function whose type checking is disabled at call and returning nothing.