a strange use of typedef - c++

I have never see a grammar in c++ like this before:
typedef int (callback)(int);
what really does this really mean?I just find that if I create a statement
callback a;
It's effect is very very similar to a forward function declaration.
below is the code I had written
#include<cstdio>
int callbackfunc(int i)
{
printf("%d\n",i);
return i*i;
}
// you can also use typedef int (callback)(int) here!
typedef int (*callback)(int);
void func(callback hook)
{
hook(hook(3));
}
int main()
{
func(callbackfunc);
getchar();
return 0;
}
You can use
typedef int (*callback)(int);//this is very common to use
in this code,but if we change it to
typedef int (callback)(int); //I'm puzzled by this !
this will also get the same result!
and I know typedef int (*callback)(int) and typedef int (callback)(int)
are two completely different stuff.

Its because of the fact that in the parameter declaration, the function-type is adjusted to become a pointer-to-function-type.
typedef int type(int);
typedef int (*type)(int);
The first typedef defines a type which is called function-type, while the second typedef defines a type which is called pointer-to-function-type. In the parameter declaration, function-type is adjusted to become a pointer to function type.
§13.1/3 (C++03) says,
Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (8.3.5).
[Example:
void h(int());
void h(int (*)()); // redeclaration of h(int())
void h(int x()) { } // definition of h(int())
void h(int (*x)()) { } // ill-formed: redefinition of h(int())
]
An interesting example of the exclusive usage of function-type
Suppose you've a typedef, defined as:
typedef void funtype();
then you can use this to define member-function as:
struct A
{
//member function declaration.
funtype f; //equivalent to : void f();
};
void A::f() //definition
{
std::cout << "haha" << std::endl;
}
Test code:
int main() {
A a;
a.f(); //call member function
}
Output:
haha
Online demo: http://ideone.com/hhkeK

It's because a function implicitly becomes a function pointer where necessary. These are identical:
func(callbackfunc);
func(&callbackfunc);

Related

Can I put a throw declaration in a typedef function signature?

Is it possible to declare a function pointer including the throw specification? For example, I have this function:
void without_throw() throw() {
}
And would like to to create a function that accepts it as a parameter, complete with the throw() part. I've tried adding it to the typedef, but that doesn't seem to work:
typedef void (*without)() throw();
GCC gives me the error error: ‘without’ declared with an exception specification.
You can't typedef that. It's explicitly not allowed in the standard. (And replacing that with noexcept doesn't help, same problem.)
Quoting C++11 draft n3290 (§15.4/2 Exception specifications)
An exception-specification shall appear only on a function declarator for a function type, pointer to function type, reference to function type, or pointer to member function type that is the top-level type of a declaration or definition, or on such a type appearing as a parameter or return type in a function declarator. An exception-specification shall not appear in a typedef declaration or alias-declaration. [ Example:
void f() throw(int); // OK
void (*fp)() throw (int); // OK
void g(void pfa() throw(int)); // OK
typedef int (*pf)() throw(int); // ill-formed
– end example]
The second example allows you to do something like this:
void foo() throw() {}
void bar() {}
int main()
{
void (*fa)() throw() = foo;
void (*fb)() throw() = bar; // error, does not compile
}
Also you can use std::function if c++0x is acceptable:
#include <functional>
void without_throw() throw() {}
typedef std::function<void() throw()> without;
int main()
{
without w = &without_throw;
w();
}

How does this example in standard section 6.8 works?

In standard Section §6.8 of the Standard (N3690 draft) I see this weird piece of code :
struct T2 { T2(int){ } };
int a, (*(*b)(T2))(int), c, d;
What is int(*(*b)(T2))(int) ?!
Is b a pointer to T2's constructor ?! or maybe a pointer to function pointer ?
It's weird that the bellow code also compile fine !:
struct T2 { T2(int){ } };
int((*b)(T2));
int (*(*b)(T2))(int)
It declares b as pointer to a function which:
takes T2 as argument
and returns pointer to a function which
takes an int as argument
and returns an int.
One should simplify this declaration using typedefs as:
typedef int (*return_type) (int);
typedef return_type(*function_type) (T2);
Or better use C++11 style type aliases:
using return_type = int(*)(int);
using function_type = return_type(*)(T2);
Then the declaration becomes this:
function_type b; //so simple!
Hope that helps.
It is declaration of variable b. b is a pointer to function with one parameter of type T2. The return type of this function is pointer to function with one parameter int returning int.
This should help you understand what is going on here:
struct T2 { T2(int){ } };
typedef int (*func)(int);
int
(*foo(T2))(int) {
}
func
bar(T2) {
}
int main() {
int (*(*b)(T2))(int);
b = &foo;
b = &bar;
return 0;
}
So this is a function that take a T2 and return a function pointer to a function that return an int and take an int as parameter.
I a add this to my example of why c(++) is an horrible language.
By the way, you cannot take the address of a constructor (C++98 Standard 12.1/12 Constructors - "12.1-12 Constructors - "The address of a constructor shall not be taken.")

C++ template: retain non-type value info without store in the constructor

Suppose I have following template class:
template<unsigned char I, unsigned char F>
class FOO
{
....
}
In the main function, I have many such variables, with different (I, F), like following,
int main()
{
.....
FOO<4, 2> a;
FOO<6, 3> b;
......
}
I want to retain the value of I or F for the defined variables in my main function. Of course, I can define a public/private members for FOO and save the value of (I, F) inside the FOO's constructor, like
template<I,F>
FOO<I,F>::FOO(){
i = I;
f = F;
}
Disadvantage of this method is obvious: It enlarge the size of the FOO. IMO, (I, F) of any variable can be determined at compiling time, so there should be a way to do this without creating local variable.
The usual way (like std::array in C++11) is to do the following:
constexpr unsigned char i() const { return I; }
constexpr unsigned char f() const { return F; }
If your compiler doesn't support constexpr, remove it.
Within your class definition, you can simply refer to the parameters literally (just like any other template parameters!).
But suppose you have this:
typedef Foo<10, 20> MyFoo;
MyFoo x; // what is I, what is K?
The customary thing is to reflect the template parameters inside the class definition:
template <int A, typename T> struct Foo
{
static int const a_value = A;
typedef T type;
// ...
};
Now you can say: MyFoo::type x; return MyFoo::a_value; etc. Note that integral static class constants don't usually need a definition unless you do something like take their address, so in most cases this won't have any cost in the compiled code -- the compiler simply substitutes the value whenever it sees the name of the constant.
you can simply use the template parameters, like this:
#include <iostream>
using namespace std;
template<unsigned char I, unsigned char F>
class FOO
{
public:
void bar() {
cout << "I is: "<<I<<endl;
}
char getI() {
return I;
}
};
using namespace std;
int main(){
FOO<4,2> a;
a.bar();
cout << "getI:"<<a.getI()<<endl;
}
you don't need a copy, as in your example (i = I)
BTW: fully capitalized names like FOO are usually by convention reserved for preprocessor Macros.

Non-pointer typedef of member functions not allowed?

After getting an answer to this question I discovered there are two valid ways to typedef a function pointer.
typedef void (Function) ();
typedef void (*PFunction) ();
void foo () {}
Function * p = foo;
PFunction q = foo;
I now prefer Function * p to PFunction q but apparently this doesn't work for pointer-to-member functions. Consider this contrived example.
#include <iostream>
struct Base {
typedef void (Base :: *Callback) ();
//^^^ remove this '*' and put it below (i.e. *cb)
Callback cb;
void go () {
(this->*cb) ();
}
virtual void x () = 0;
Base () {
cb = &Base::x;
}
};
struct D1 : public Base {
void x () {
std :: cout << "D1\n";
}
};
struct D2 : public Base {
void x () {
std :: cout << "D2\n";
}
};
int main () {
D1 d1;
D2 d2;
d1 .go ();
d2 .go ();
}
But if I change it to the new preferred style: typedef void (Base :: Callback) () and Callback * cb, I get a compiler error at the point of typedef
extra qualification 'Base::' on member 'Callback'
Demo for error.
Why is this not allowed? Is it simply an oversight or would it cause problems?
For non-member functions, a type such as typedef void(Function)() has several uses, but for member functions the only application is to declare a variable which holds a function pointer. Hence, other than a stylistic preference, there's no strict need to allow this syntax and it has been omitted from the standard.
Background
The :: is a scope resolution operator, and the syntax X::Y is reserved for static member access if X is a class type. So X::*Z was another syntax invented to define pointer-to-member.
Forget member-function for a while, just think about member-data, and see this code:
struct X
{
int a;
};
int X::*pa = &X::a; //pointer-to-member
X x = {100}; //a = 100
cout << (x.*pa) << endl;
It defines a pointer-to-member-data, and the cout uses it to print the value of a of object x, and it prints:
100
Demo : http://www.ideone.com/De2H1
Now think, if X::pa (as opposed to X::*pa) were allowed to do that, then you've written the above as:
int X::pa = X::a; //not &X::a
Seeing this syntax, how would you tell if X::a is a static member or non-static member? That is one reason why the Standard came up with pointer-to-member syntax, and uniformly applies it to non-static member-data as well as non-static member-function.
In fact, you cannot write X::a, you've to write &X::a. The syntax X::a would result in compilation error (see this).
Now extend this argument of member-data to member-function. Suppose you've a typedef defined as:
typedef void fun();
then what do you think the following code does?
struct X
{
fun a;
};
Well, it defines member a of type fun (which is function taking no argument, and returning void), and is equivalent to this:
struct X
{
void a();
};
Surprised? Read on.
struct X
{
fun a; //equivalent to this: void a();
};
void X::a() //yes, you can do this!
{
cout << "haha" << endl;
}
We can use exactly the same syntax to refer to a which is now a member-function:
X x;
x.a(); //normal function call
void (X::*pa)() = &X::a; //pointer-to-member
(x.*pa)(); //using pointer-to-member
The similarity is the synatax on the right hand side : &X::a. Whether a refers to a member-function or member-data, the syntax is same.
Demo : http://www.ideone.com/Y80Mf
Conclusion:
As we know that we cannot write X::a on the RHS, no matter if a is a member-data or member-function. The only syntax which is allowed is &X::f which makes it necessary that the target type (on LHS) must be pointer as well, which in turn makes the syntax void (X::*pa)() absolutely necessary and fundamental, as it fits in with other syntax in the language.
To be precise the two typedef's in the case of the non-member pointers are not the same:
typedef void function();
typedef void (*fptr)();
The first defines function as a function taking no arguments and returning void, while the second defines ftpr as a pointer to function taking no arguments and returning void. The confusion probably arises as the function type will be implicitly converted to a pointer type in many contexts. But not all:
function f; // declares void f();
struct test {
function f; // declares void test::f()
};
void g( function f ); // declares g( void (*f)() ): function decays to pointer to function in declaration
g( f ); // calls g( &f ): function decays to pointer to function
void f() {} // definition of f
// function h = f; // error: cannot assign functions
function *h = f; // f decays to &f
Let's skip the "function" part for a second. In C++, we have the int, the int* and the int Foo::* types. That's a regular integer, pointer to integer, and a pointer to an integer member. There is no fourth type "integer member".
Exactly the same applies to functions: there's just no type "member function", even though there are function types, function pointer types, and member function pointer types.

Reference to Function syntax - with and without &

What's the difference between
typedef void (&FunctionTypeR)();
vs
typedef void (FunctionType)();
Is the second also a reference to function? Is FunctionTypeR equivalent to FunctionType& when used as the type of an argument?
For
void foo(FunctionType bar)
Does the runtime makes a copy of the argument bar (a function) when foo is invoked?
The difference is that you cannot create objects of function type, but you can create of objects of function pointer type, and function reference type.
That means if you've a function, say f() as:
void f(){}
then here is what you can do, and what you cannot do:
FunctionType fun1 = f; //error - cannot create object of function type
FunctionType *fun2 = f; //ok
FunctionTypeR fun3 = f; //ok
Test code:
typedef void (&FunctionTypeR)();
typedef void FunctionType();
void f(){}
int main() {
FunctionType fun1 = f; //error - cannot create object of function type
FunctionType *fun2 = f; //ok
FunctionTypeR fun3 = f; //ok
return 0;
}
Now see the compilation error (and warnings):
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: function ‘void fun1()’ is initialized like a variable
prog.cpp:8: warning: unused variable ‘fun2’
prog.cpp:9: warning: unused variable ‘fun3’
Online demo : http://ideone.com/hpTEv
However, if you use FunctionType (which is a function type) in a function parameter list as:
void foo(FunctionType bar);
then it's equivalent to
void foo(FunctionType * bar);
That means, no matter what you write, you can call the function using bar as:
bar(); //ok
(*bar)(); //ok
That is, you can write this:
void h(FunctionType fun) { fun(); }
void g(FunctionType fun) { (*fun)(); }
Demo : http://ideone.com/kwUE9
This is due to function type to function pointer type adjustment; that is, the function type is adjusted to become a pointer to function type:
Function type | Function pointer type (adjusted type)
void () | void (*)()
void (int) | void (*)(int)
int (int,int) | int (*)(int,int)
.... | ... so on
The C++03 Standard says in §13.1/3,
Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (8.3.5).
[Example:
void h(int());
void h(int (*)()); // redeclaration of h(int())
void h(int x()) { } // definition of h(int())
void h(int (*x)()) { } // ill-formed: redefinition of h(int())
]
And if you use `FunctionTypeR (which is a function reference type) as:
void foo(FunctionTypeR bar);
then it's equivalent to:
void foo(FunctionType * & bar);
And,
void h(FunctionTypeR fun) { fun(); }
void g(FunctionTypeR fun) { (*fun)(); }
Demo : http://ideone.com/SmtQv
Interesting part...
You can use FunctionType to declare a function (but not to define it).
For example,
struct A
{
//member function declaration.
FunctionType f; //equivalent to : void f();
};
void A::f() //definition
{
std::cout << "haha" << std::endl;
}
//forward declaration
FunctionType h; //equivalent to : void h();
int main() {
A a;
a.f(); //call member function
h(); //call non-member function
}
void h() //definition goes below main()
{
std::cout <<"hmmm.." << std::endl;
}
Demo : http://ideone.com/W4ED2