13

I'd like to know what this expression means??

typedef bool (*compareShapes)(const Shape* s1, const Shape* s2); 

The Shape is a class.

5
  • Isn't it *compareShapes? in which case it's a function pointer typedef. Commented Nov 23, 2016 at 14:09
  • 1
    seems very much like a function pointer. that means any function, that takes one shape by value and one by pointer, can be assigned to compareShapes. you can achieve generic algorithm with this way. see qsort for an example where this is used. another approach would be a template, see std::sort to see how the same idea is done with a template Commented Nov 23, 2016 at 14:11
  • You may be wondering why it's a declaration of a pointer to a function rather than a function itself. The reason is that functions cannot be passed around and returned by value; you can only do that with a pointer to it. Commented Nov 23, 2016 at 19:29
  • cdecl.org Commented Nov 24, 2016 at 5:25
  • What does a typedef with parenthesis like “typedef int (f)(void)” mean Commented Nov 24, 2016 at 5:27

7 Answers 7

27

You should be using using-statements. It make the very same declaration easier to read:

using compareShapes = bool(*)(const Shape*, const Shape*); 

See it now? the type is after the equal sign. It's a pointer to function type.

One could declare it like this too:

// function pointer type --v----------------------------------------------------v using compareShapes = std::add_pointer_t< bool(const Shape*, const Shape*) >; // function signature -----^------------------------------^ 

The function signature is composed like this:

<return-type>( <arguments...> ) 

When you add the pointer in it, it looks like this:

<return-type>(*)( <arguments...> ) 

And if you add the pointer name or type name here, add it after the star:

<return-type>(*typeOrPointerName)( <arguments...> ) 
Sign up to request clarification or add additional context in comments.

9 Comments

Nice clarification!
Maybe my view is unpopular, but I find the typedef easier to read in many cases, including this one.
Maybe I'm an old fart, but my reaction is "oh god, not another way to write the same damn thing that I have to remember now".
While I'm like "wait, there was an old way? Ugh, that was so ugly. Glad the new way exists"
The question is "i'm reading code and found this, what is it?", why is the highest rated answer "you should do this instead"? o.O
|
16

Well, it's a typedef, so there are two parts - the type, and the new name being defined for it.

The first part is the type:

bool (*)(const Shape* s1, const Shape* s2); 

which is a pointer to a function, taking two pointer-to-const-Shape arguments, and returning bool.

The second part is the name of the type: compareShapes. Admittedly function pointer typedefs are tricky to read, but that's partly just because function pointer syntax isn't used very often.

So, for example, I can write any number of compatible functions:

bool identical(const Shape *a, const Shape *b); bool strictlyContained(const Shape *a, const Shape *b); bool topologicallyEquivalent(const Shape *a, const Shape *b); 

which tells me whether a is identical to b, or wholly inside b, or whether a and b have the same number of holes.

Then, I can write code which works with any comparison, and choose which to use later, like:

compareShapes cmp; if (shouldUseIdentityComparison()) { cmp = &identical; } else if (shouldUseInsideComparison()) { cmp = &strictlyContained; } else { cmp = &topologicallyEquivalent; // ... if (cmp(a,b)) { // they're equal, for whichever comparison we chose above } 

It's probably more common in modern code to either write a template, taking an arbitrary comparator type (as in std::sort), or to write a non-template function taking std::function<bool(const Shape*, const Shape*)>, which is more flexible than a raw function pointer.

C doesn't (and earlier versions of C++ didn't) have these facilities, so had to use function pointers. I suspect they're mostly used for backwards-compatibility with older code, and possibly in resource-constrained environments.

Comments

12

compareShapes is alias for function pointer, which accepts 2 const Shape* and return bool

compareShapes func = [] (const Shape* s1, const Shape* s2) -> bool { return *s1 == *s2; //something boolean }; bool result = func(s1, s2); 

Or another example, if you already have function:

bool someFunc(const Shape* s1, const Shape* s2) { return true; } compareShapes funcPtr = someFunc; bool result = funcPtr(s1, s2); 

More about function pointers is available HERE

Comments

6

To add some detail to the comments:

This is a function pointer. The typedef is there to make it easier to use. Ordinarily typedefs have the form "typedef actual_type new_easier_name". Ex:

typedef int i 

Obviously that line would never appear in practice. But for more complicated types (especially those involving pointers and templates), using a typedef can make your code much more readable.

This expression is giving the name "compareShapes" to a function pointer type. In this case, that type is a function that takes pointers to two Shape objects and returns a boolean. This way, code to assign a function to the pointer and call it is much more clear.

Here's an example that might appear in practice. Assume Shape has at least two fields: perimeter and area. A user might want to sort on either of them:

#include <vector> bool perimeterComparison(const Shape* a, const Shape* b){ return a->perimeter <= b->perimeter; } bool areaComparison(const Shape* a, const Shape* b){ return a->area <= b->area; } //Note the capitalization of CompareShapes to show it is a type, not a variable typedef bool (*CompareShapes)(const Shape* a, const Shape* b); void sortShapes(std::vector<Shape*>& shapes, CompareShapes comparison){ //Lazy programming: bubble sort for(int first = 0; first < shapes.length(); shapes++){ for(int second = first + 1; second < shapes.length(); shapes++){ if(!comparison(shapes[first], shapes[second])){ Shape* temp = shapes[second]; shapes[second] = shapes[first]; shapes[first] = shapes[second]; } } } } int main(){ //This could just as easily point to perimeterComparison or something else valid CompareShapes compareFunction = &areaComparison; std::vector<Shape*> shapes(10); for(int i = 0; i < 10; i++){ shapes[i] = new Shape(); //Initialize the shapes somehow } sortShapes(shapes, compareFunction); for(int i = 0; i < 10; i++){ cout << shapes[i] << "\n"; } return 0; } 

3 Comments

"Obviously that line would never appear in practice". MIcrosoft wants a WORD with you.
your example isnt the very best, because this particular example would be even easier too read without using a function pointer at all. imho a better example would be a function that takes e.g. two shapes and a pointer to a comparison function as parameter.
@tobi303 You are both totally right; I was merely trying to demonstrate the syntax, not context. I'll update the example. ROFL from Revolver_Ocelot's comment.
2

You can use cdecl to interpret such types, but you need to insert struct before the class names, and replace bool for it to parse as C code:

cdecl> explain struct bool (*compareShapes)(const struct Shape* , const struct Shape* ) declare compareShapes as pointer to function (pointer to const struct Shape, pointer to const struct Shape) returning struct bool 

You then need to mentally undo that transformation, giving

declare compareShapes as pointer to function (pointer to const Shape, pointer to const Shape) returning bool

Comments

1

compareShapes is a function pointer which takes 2 parameter of type (pointer to Shape) and returns boolean value.

You can assign compareShapes any function which fits this signature.

So for example,

bool isShapesValid(const Shape* s1, const Shape* s2) 

can be assigned:

compareShapes objCompareShapes = &isShapesValid; 

Comments

0
typedef bool (*compareShapes)(const Shape* s1, const Shape* s2); bool CmpShapes(const Shape *s1,const Shape *s2){retunr true;} 

compareShapes is a function prototype (signature) who compares two Shape objects

for example:

class Shape{}; class CTest{ compareShapes m_cmp; public: CTest(compareShapes _cmpFunc):m_cmp(_cmpFunc){ printf("m_cmp: %p %s\n",m_cmp,m_cmp(NULL,NULL)?"true":"false"); }; }; void main(){ Ctest tst(&CmpShapes);//we pass CmpShapes address. } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.