Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ function types

I have a problem understanding function types (they appear e.g. as the Signature template parameter of a std::function):

typedef int Signature(int); // the signature in question  typedef std::function<int(int)>  std_fun_1; typedef std::function<Signature> std_fun_2;  static_assert(std::is_same<std_fun_1, std_fun_2>::value,               "They are the same, cool.");  int square(int x) { return x*x; }  Signature* pf = square;   // pf is a function pointer, easy Signature f;              // but what the hell is this? f(42);                    // this compiles but doesn't link 

The variable f can not be assigned, but can be called. Weird. What is it good for, then?

Now if I const-qualify the typedef, I can still use it to build further types but apparently for nothing else:

typedef int ConstSig(int) const;  typedef std::function<int(int) const>  std_fun_3; typedef std::function<ConstSig>        std_fun_4;  static_assert(std::is_same<std_fun_3, std_fun_4>::value,               "Also the same, ok.");  ConstSig* pfc = square; // "Pointer to function type cannot have const qualifier" ConstSig fc;            // "Non-member function cannot have const qualifier" 

What remote corner of the language have I hit here? How is this strange type called and what can I use it for outside of template parameters?

like image 362
marton78 Avatar asked Jul 03 '13 11:07

marton78


People also ask

What is function in C with example?

1) Predefined standard library functions h extensions are called header files such as stdio. h ), so we just call them whenever there is a need to use them. For example, printf() function is defined in <stdio. h> header file so in order to use the printf() function, we need to include the <stdio.

What are the 3 aspects in each C function?

There are 3 aspects in each C function. They are, Function declaration or prototype – This informs compiler about the function name, function parameters and return value's data type.


2 Answers

Here's the relevant paragraph from the Standard. It pretty much speaks for itself.

8.3.5/10

A typedef of function type may be used to declare a function but shall not be used to define a function (8.4).

Example:

typedef void F(); F  fv;         // OK: equivalent to void fv(); F  fv { }      // ill-formed void fv() { }  // OK: definition of fv 

A typedef of a function type whose declarator includes a cv-qualifier-seq shall be used only to declare the function type for a non-static member function, to declare the function type to which a pointer to member refers, or to declare the top-level function type of another function typedef declaration.

Example:

typedef int FIC(int) const; FIC f;               // ill-formed: does not declare a member function struct S {   FIC f;             // OK }; FIC S::*pm = &S::f;  // OK 
like image 187
aschepler Avatar answered Oct 10 '22 06:10

aschepler


In your case, std_fun_1 and std_fun_2 are identical objects with identical type signatures. They are both std::function<int(int)>, and can both hold function pointers or callable objects of type int(int).

pf is a pointer to int(int). That is, it serves the same basic purpose as std::function, but without the machinery of that class or support for instances of callable objects.

Similarly, std_fun_3 and std_fun_4 are identical objects with identical type signatures, and can both hold function pointers or callable objects of type int(int) const.

Also similarly, pfc is a function pointer of type int(int) const, and can hold pointers to functions of that type, but not instances of callable objects.

But f and fc are function declarations.

The line:

Signature fc; 

Is identically equivalent to:

int fc(int) const; 

Which is a declaration for a function named fc of type int(int) const.

There's nothing strange going on here. You've simply happened upon syntax you probably already understand, from a perspective you're not accustomed to.

like image 30
greyfade Avatar answered Oct 10 '22 06:10

greyfade