Objects w/ no type?!!?

P

Protoman

Read this code I found on the Internet:

Object o,*oo; // Some objects
int (Object::*ptr_to_o_func)(double);
// ptr_to_obj_func is a pointer to a
// member function of Object

oo = getObjectPtr();

ptr_to_o_func = (//some boolean condition) ?
&Object::foo : &Object::bar;

std::cout << "Value is " <<
(o.*ptr_to_o_func)(3.14) + (oo->*ptr_to_o_func)(2.72)
<< endl;

o.*ptr_to_o_func and oo->*ptr_to_o_func are functors. Aren't functors
like clsures that bind together an object w/ a pointer to one of it's
member functions? I heard they don't have a type. What? What if they
did have a type? How can the compile type-check them? Thanks!!!!
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

Read this code I found on the Internet:

Object o,*oo; // Some objects
int (Object::*ptr_to_o_func)(double);
// ptr_to_obj_func is a pointer to a
// member function of Object

oo = getObjectPtr();

ptr_to_o_func = (//some boolean condition) ?
&Object::foo : &Object::bar;

std::cout << "Value is " <<
(o.*ptr_to_o_func)(3.14) + (oo->*ptr_to_o_func)(2.72)
<< endl;

o.*ptr_to_o_func and oo->*ptr_to_o_func are functors. Aren't functors
like clsures that bind together an object w/ a pointer to one of it's
member functions? I heard they don't have a type. What? What if they
did have a type? How can the compile type-check them? Thanks!!!!

o.*ptr_to_o_func and oo->*ptr_to_o_func are member function calls, and
their type (if they can be said to have any) is the type of the return
type of the function calls (in this case int).

I'm not sure you can claim that they have a type since they are
statements, you tell the computer to do something, in this case call the
function pointed to by ptr_to_o_func on the obects o and the object
pointed to by oo.
 
P

Protoman

o.*ptr_to_o_func and oo->*ptr_to_o_func are member function calls, and
their type (if they can be said to have any) is the type of the return
type of the function calls (in this case int).

I'm not sure you can claim that they have a type since they are
statements, you tell the computer to do something, in this case call the
function pointed to by ptr_to_o_func on the obects o and the object
pointed to by oo.

Yes, I know but this guy says they have no type;
http://www.everything2.com/index.pl?node=C++: objects with no type
 
R

Robert Bauck Hamar

Protoman said:
Yes, I know but this guy says they have no type;
http://www.everything2.com/index.pl?node=C++: objects with no type

This person is either confused, or he is using a different definition of
type than the standard. His argument is that because

o.*ptr_to_o_func

cannot be assigned to anything, it has no type. Odd that he has never tried

o.foo,

which has the same "problem". Both o.*ptr_to_o_func and o.foo has the same
type: "The expression designates a nonstatic member function" says the
standard in 5.2.5. Such an expression can only be used with the function
call operator.
 
P

Protoman

http://www.everything2.com/index.pl?node=C++: objects with%...

This person is either confused, or he is using a different definition of
type than the standard. His argument is that because

o.*ptr_to_o_func

cannot be assigned to anything, it has no type. Odd that he has never tried

o.foo,

which has the same "problem". Both o.*ptr_to_o_func and o.foo has the same
type: "The expression designates a nonstatic member function" says the
standard in 5.2.5. Such an expression can only be used with the function
call operator.

OK. BTW, are C++ functors lke closures in other languages? Like
"frozen" functions?
 
J

James Kanze

I'm not sure. Functors are normally objects, not expressions.
you can't assign "o.*ptr_to_o_func" to anything, for example.

Again, not necessarily. The usual definition is that they are
objects which can be "called"; objects for which the () operator
is defined.

No they're not. They're "pm-expression"s, according to the
standard. And (again, according to the standard) their type is
"an object or a function of the type specified by the second
operand", here, a function. The resulting expression has the
type "function (double) returning int". And since the
expression isn't an lvalue, you can't take its address. In a
sense, C++ has closures, but only as temporary "objects", like
here.

That's the type of the results of the () operator, once it's
applied to the above expression.

I think they have a type. The standard says that they have a
"function" type.
Yes, I know but this guy says they have no type;http://www.everything2.com/index.pl?node=C++: objects with%...

He's wrong. He just doesn't understand C++ typing as it applies
to functions. (But I'll admit that it's not always evident.)
 
?

=?iso-8859-1?q?Kirit_S=E6lensminde?=

TW, are C++ functors lke closures in other languages? Like
"frozen" functions?

Sort of. You can make something that is very close to a closure (ahem)
with a functor. You can also use them to do something similar to
currying.

struct power {
power( float second ) m_pow( second ) {}
float operator()( float first ) const { return std::powf( first,
m_pow ); };
private:
float m_pow;
};

power now acts like a curried version of std::powf - although beware,
I'm binding the second argument not the first so in a language like
Haskell you'd need to use flip too.

power cube( 3 );
cube( 10 ); // Will return 1,000

Note that the implementation of power uses what could be seen as a
closure. In C++ you don't get automatic closure of arguments within
the same lexical scope. You have to put them into the closing
structure yourself.

All of this is much clearer using Boost.Function and Boost.Lambda
where you can play with functional idioms more easily.

If you want to see this sort of thing in action, consider a function
for executing some script and returning a result. The lambda that will
execute the script has this type:

boost::function< _variant_t ( wstring ) >

This means that it takes a wstring (the source) and produces a
_variant_t (a wrapper for the Windows COM type VARIANT) which is the
result of the script execution.

Now to store a context for dynamic execution of a script I have this:

class Translator { // Creates HTML from some internal format
// snip
boost::function< _variant_t ( wstring ) > dynWriter;
};

I initialise this through a function that looks like this (abridged
slightly to make it clearer what is going on from some code for a
multi-threading JavaScript host):

boost::function< _variant_t ( wstring ) > embed() {
boost::shared_ptr< Mahlee > mahlee( new Mahlee );

return boost::lambda::bind(
&Mahlee::run,
boost::lambda::bind(
&boost::shared_ptr< FSLib::process::Mahlee >::get,
mahlee ),
boost::lambda::_1 );
}

The first line creates a JavaScript interpreter and puts it into a
shared_ptr. For the lambdas it makes two. The inner one simply creates
a closure around the mahlee object and allows us to get the object
pointed to through the shared_ptr's get member.

The outer lambda then creates a functor object that embeds the
following:

mahlee->run( _1 )

This is stored in the dynWriter member earlier:

dynWriter = embed();

Now dynWriter has become a function that given some JavaScript
executes it and returns the result of the code into a _variant_t:

dynWriter( L"function() { return 'Hello world!'; }()" );

This will return a _variant_t with the string Hello world! in it.

The hardest part doing this in C++ is that you have to be very careful
to think through the full implications of object lifetimes. You can
see a more advanced use that shows the difference between generalised
partial application and currying on the second half of this page from
my web site: http://www.kirit.com/News:/1720702


K
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,291
Messages
2,571,493
Members
48,164
Latest member
KerrieWind

Latest Threads

Top