Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

function type inside template

21 views
Skip to first unread message

porp...@gmail.com

unread,
Apr 26, 2017, 11:54:22 AM4/26/17
to
Hi,

When I create an object of type boost::function I do it e.g. as follows:
boost::function<int(int,int)> boostFun2;

Why I cannot create an object of type int(int,int) ? e.g.
int(int,int) myFun;

great thanks for help

Marcel Mueller

unread,
Apr 26, 2017, 12:26:58 PM4/26/17
to
On 26.04.17 17.54, porp...@gmail.com wrote:
> When I create an object of type boost::function I do it e.g. as follows:
> boost::function<int(int,int)> boostFun2;
>
> Why I cannot create an object of type int(int,int) ? e.g.
> int(int,int) myFun;

because the syntax is wrong. The name has to be /before/ the braces.

int myFun(int,int);
declares a matching function.

But, of course, this is not a function object. There are no function
objects in the C/C++ language. They are part of the class library, e.g.
std::function<> or boost::function.


Marcel

Alf P. Steinbach

unread,
Apr 27, 2017, 1:17:16 AM4/27/17
to
On 26-Apr-17 5:54 PM, porp...@gmail.com wrote:
>
> When I create an object of type boost::function I do it e.g. as follows:
> boost::function<int(int,int)> boostFun2;
>
> Why I cannot create an object of type int(int,int) ? e.g.
> int(int,int) myFun;

Shortest possible explanation: there's no syntax for that.

But that short explanation ignores why there's no such syntax, so let's
delve into that.

Some computers (mostly digital signal processors) have Harvard
architecture where machine code is kept in one memory, and data in
another. Or at least it works as if that were the case. So a given
address can mean one thing when used as a code memory address, and
another when used as a data memory -- ordinary memory -- address.

C++ and most conventional languages only support dealing directly with
contents of data memory. When you declare a variable it's an abstraction
of a piece of data memory. When you change the value of an object it's
change of data memory contents.

The language doesn't support inspecting or changing contents of code
memory except that on most machines you can get at it via data memory,
because on most machines, with von Neumann architecture, those memories
and address spaces are in fact one and the same, the unification of code
and data which Johann von Neumann (undeservedly) got famous for.

However, C++ supports dealing with code memory addresses as /function
pointers/. I.e. a data memory object that contains the start address of
a function's machine code in code memory. You can't portably inspect the
machine code at such an address, but you can copy these pointers around,
in data memory, and you can invoke a function pointed to.

Here's an example:

#include <iostream>
using namespace std;

using My_func = auto(int, int) -> int;

void do_something_with( My_func* const f )
{
auto const addr = reinterpret_cast<void const*>( f );
cout << "It's function address " << addr << ".\n";
cout << "f(2, 3) = " << f(2, 3) << "\n";
}

auto foo( int a, int b ) -> int { return a*b; }

auto main()
-> int
{ do_something_with( &foo ); }

The cast to `void*` here, for the purpose of outputting the address, is
not necessarily supported by any particular compiler. With C++11 and
later is allowed to optionally support this, and most compilers do. But
a compiler for a Harvard architecture digital signal processor may not
necessarily support it, so even in practice this is not entirely
portably code.

A possibly more portable alternative is to use a cast to `uintptr_t`,
but that's less convenient.

Anyway, C++ has special support for function pointers. For example, as
shown above, instead of writing `(*f)(2, 3)` you can write just `f(2,
3)`, as if the pointer were directly the name of a function.

Also, instead of `My_func* f` (no `const`) you can write just `My_func
f` as formal argument type, and because it is a formal argument type you
get an automatic DECAY to pointer type, not just of the argument name
used in an expression, but of the actual type of the argument. Which
baffles many a novice. There's a corresponding decay of array to pointer
to item.

For both pointers and arrays there are also such decays for function and
array names used in expressions, i.e. decays of expression value type.
E.g. instead of `&foo` above, to get the address of `foo`, I could have
written just `foo`. Happily these value type decays do not occur when
you bind a function or array to a reference.

Also, if you write

My_func f;

at namespace scope, then (as opposed to the literally same declaration
as a formal argument) there's no type decay, and the result is not a
data memory object but a declaration of a function in code memory.

A definition of the function can't have that form -- there's no syntax
for that -- but it's possible to just declare a function this way. I
do not know what the rationale is. I've never needed it.


Cheers & hth.,

- Alf

Juha Nieminen

unread,
May 2, 2017, 2:48:38 AM5/2/17
to
porp...@gmail.com wrote:
> Why I cannot create an object of type int(int,int) ? e.g.
> int(int,int) myFun;

The syntax to get a function pointer is a bit weird (and comes from C).
You have to write it as:

int(*myFun)(int, int);

In C++11 you kind of get closer by using the 'using' keyword, like so:

using Func = int(int, int);
Func* myFun = someFunction;
0 new messages