johnbakers
johnbakers

Reputation: 24750

Using auto for a defined function

I've used auto to store a lambda that is constructed right in the auto assignment, but today I was looking at this interesting paper on functional programming using c++ templates and came across this code:

template < typename T , typename Ops >
T fold ( Linked <T > * p )
{
   T acc = Ops :: initial () ;
   while ( p ) {
     acc = Ops :: bin ( acc , p - > head ) ;
     p = p - > tail ;
   }
   return acc ;
}

// later, in main():

auto sumup = fold <int , IntOps >;

I am trying to understand what the type of sumup would be, since it is assigned not to the output of fold but rather to the actual function fold itself! I decided to take a look at the various ways auto is shown to be used here. I am assuming that this use of auto falls under (1) on that page, a general variable initializer. What is not clear is what is the type of sumup?

And, would auto potentially be the same here as doing this:

   using functionType = int (Linked<int>*);
   functionType sumup = fold <int , IntOps >;

This is probably not correct, but I'd be curious if my thinking is in the right direction. When instantiated, fold <int , IntOps > will be a function that returns an int and taking a single argument of Linked<int>*, so my using declaration is saying the same thing? Is this using declaration a bonafide "type" and is the auto arriving at the same deduction as this using?

Upvotes: 1

Views: 179

Answers (2)

MSalters
MSalters

Reputation: 179779

While every function has a type, you cannot have expressions of that type, nor variables. So int foo(float) has type int(float), for instance, but you cannot have a variable of that type.

You can have expressions and variables of type pointer to function, so int(*)(float). For instance, &foo is such a pointer to function.

The two types are quite closely related, obviously. In fact, the conversion is implicit: int (*pFoo)(float) = foo; does the conversion automatically.

What you do here is pretty much the same: int (*sumup)(Linked<int>*) = fold <int , IntOps >;. You see that auto makes the definition much more readable.

Upvotes: 1

Yam Marcovic
Yam Marcovic

Reputation: 8141

auto works by the same rules as template argument deduction. That is, when unqualified, it will take things by value. Since here you're returning a function reference, it will have to decay down to a pointer, because there's no "value type" for a function, with a specific size and whatnot.

You could also capture with auto&& which would make the type of sumup be int (&)(Linked<int>*), i.e. a reference to the function.

Upvotes: 1

Related Questions