9

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...)

Michael
  • 706
  • 9
  • 29

3 Answers3

12

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.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • I agree 100% with your conclusion. People in the C++ world really need to start using std::function to express function pointers. Ignore the (very outdated) Google style guide and use std::function, for the love of tentacle monster gods! – Matt Holmes Jan 06 '14 at 18:31
  • 3
    Or better: `using m = n*(const n*, const n*);` – Guilherme Bernal Jan 06 '14 at 18:32
  • 1
    @MattHolmes: It is still necessary to understand and be able to write the pre-`function` syntax. Not everybody uses C++11 or Boost. – John Dibling Jan 06 '14 at 18:33
  • 1
    Is `std::function` overhead free? – RedX Jan 06 '14 at 18:33
  • @RedX: No. You get an overhead roughly equivalent to virtual calls, sometimes. http://stackoverflow.com/q/5057382/560648 – Lightness Races in Orbit Jan 06 '14 at 18:37
  • @JohnDibling: Boost has provided the 'function' template for nearly a decade, and it's been part of the C++ standard for over two years. People need to get with the times. If you are writing new code and not using std::function (or it's Boost equivalent) it's likely you're being a grognard and nothing more. Old code bases are a different monster. – Matt Holmes Jan 06 '14 at 18:38
  • @RedX: Not enough of one that you should care about it. It's about the same as a virtual function call, and if you're doing that sort of micro-optimization you shouldn't be writing C++ anyway. You should be writing raw C or assembly. – Matt Holmes Jan 06 '14 at 18:39
  • "Cthulhu" and not "Chulthu" :-) – Fredrik Pihl Jan 06 '14 at 18:40
  • 2
    @MattHolmes: It's not that simple. Consider for example that the version of GCC that comes with the RHEL distro is quite old, far pre-C++11. Many software and client shops *require* that the toolchain provided with the distro be used. Try to see the bigger picture before assuming all who don't share *your* beliefs to be "grognards". – John Dibling Jan 06 '14 at 18:41
  • @MattHolmes: To be fair there is still legacy and there are still lightweight systems. Introducing templated virtual calls and 3rd party libraries is not always okay. We don't all program for desktop PCs. I would disagree with the conclusion in that scenario is "well you shouldn't be using C++", but I _would_ agree that you're obviously not going to be using all of C++'s features, which is the case here. – Lightness Races in Orbit Jan 06 '14 at 18:43
  • I think: `typedef n* (m)(const n*, const n*);` is easier to read than: `typedef n *(m)(const n*, const n*);` Maybe that is what confused OP? Well that's where I got lost anyway. The star being on the n vs. being on the bracket. – Brandon Jan 06 '14 at 18:52
  • @CantChooseUsernames: I agree. In fact: http://kera.name/articles/2010/05/tomalaks-monday-monstrous-rant-i-align-your-asterisks/ However, even that does start to break down when the declarators become _this_ complicated. – Lightness Races in Orbit Jan 06 '14 at 18:56
5

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.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • 1
    Whether the `*` is inside or outside the parentheses makes a difference. –  Jan 06 '14 at 18:25
  • @hvd: Oops, hadn't noticed the `*` was outside the parens. – John Dibling Jan 06 '14 at 18:26
  • @hvd: Fixed & undeleted. – John Dibling Jan 06 '14 at 18:29
  • Oddly enough, I cannot undo my vote, even though you clearly did edit your answer. SO still says my vote is locked unless this answer is edited. –  Jan 06 '14 at 18:36
  • @hvd: Probably some kind of bug with the SE platform having to do with the fact that I edited before I un-deleted. Don't worry about it; the rep's not a big deal. – John Dibling Jan 06 '14 at 18:42
  • @LightnessRacesinOrbit: It's odd that the edit history does not give any indication that I edited this post. – John Dibling Jan 06 '14 at 18:46
  • Done. I think it may be because edit history remains empty during the first five-or-so minutes after posting an answer, and the vote locking relies on edit history. –  Jan 06 '14 at 18:51
  • @hvd: That must be it. In any case, I opened a meta ticket about the edit history: http://meta.stackexchange.com/questions/215153/odd-behavior-in-edit-history-when-i-edited-my-deleted-answer – John Dibling Jan 06 '14 at 18:54
1

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
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335