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

deducing the return type of a function call...

1 view
Skip to first unread message

James

unread,
Nov 26, 2009, 4:23:50 PM11/26/09
to
I am struggling to find a way to get around having to explicitly pass a
return type for the following callback scheme I am playing around with. Here
is some sample code:


#include <iostream>


template<typename T_return>
struct call_base
{
virtual T_return execute() const = 0;
};


template<typename T,
typename T_memfun,
typename T_return>
class call1
: public call_base<T_return>
{
T& m_object;
T_memfun m_memfun;


T_return execute() const
{
return (m_object.*m_memfun)();
}


public:
call1(T& object, T_memfun memfun)
: m_object(object),
m_memfun(memfun)
{

}
};


template<typename T,
typename T_memfun>
class call1<T, T_memfun, void>
: public call_base<void>
{
T& m_object;
T_memfun m_memfun;


void execute() const
{
(m_object.*m_memfun)();
}


public:
call1(T& object, T_memfun memfun)
: m_object(object),
m_memfun(memfun)
{

}
};


template<typename T_return>
struct call
{
typedef call_base<T_return> const& handle;


template<typename T, typename T_memfun>
static call1<T, T_memfun, T_return>
create(T& obj, T_memfun memfun)
{
return call1<T, T_memfun, T_return>(obj, memfun);
}
};


#define CALL_CREATE(name, return_type, type, memfun) \
call<return_type>::handle name = \
call<return_type>::create((type), (memfun))


struct foo
{
int display1()
{
std::cout << "("
<< this
<< ")->foo::display1()"
<< std::endl;

return 123456;
}


void display2()
{
std::cout << "("
<< this
<< ")->foo::display2()"
<< std::endl;
}
};


int
main()
{
{
foo f;

CALL_CREATE(my_call1, int, f, &foo::display1);
CALL_CREATE(my_call2, void, f, &foo::display2);

std::cout << "my_call1 returned: "
<< my_call1.execute()
<< std::endl
<< std::endl;

std::cout << "my_call2 returns void"
<< std::endl;

my_call2.execute();
}

return 0;
}

As you can see, I am explicitly passing in the return type to the
CALL_CREATE function macro. Can anyone think of a way around this? I sure
can't!

:^(

Marcel Müller

unread,
Nov 26, 2009, 4:28:18 PM11/26/09
to
James wrote:
> I am struggling to find a way to get around having to explicitly pass a
> return type for the following callback scheme I am playing around with.

Well, boost::lambda already failed to solve this problem.

Again you need C++0x. The support for type inference should solve your
problem. (not tested)


Marcel

Alf P. Steinbach

unread,
Nov 26, 2009, 5:00:30 PM11/26/09
to
* James:

> I am struggling to find a way to get around having to explicitly pass a
> return type for the following callback scheme I am playing around with.

Use boost::bind and boost::function.


Cheers & hth.,

- Alf

Frank Neuhaus

unread,
Nov 26, 2009, 4:42:54 PM11/26/09
to
Hey,

"James" <n...@spam.invalid> schrieb im Newsbeitrag
news:hemrjd$jbm$1...@aioe.org...


> I am struggling to find a way to get around having to explicitly pass a
> return type for the following callback scheme I am playing around with.
> Here is some sample code:

Maybe this can help you?
http://www.boost.org/doc/libs/1_35_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html

James

unread,
Nov 26, 2009, 6:07:26 PM11/26/09
to
"Frank Neuhaus" <fneu...@uni-koblenz.de> wrote in message
news:hemspm$3hv$1...@cache.uni-koblenz.de...

How in the heck does it determine all of those traits? Anyway, I don't think
it would work for me unless I could do something like:


int foo()
{
return 0;
}


void blah()
{
typedef function_traits<foo>::result_type return_type;
}


and have return_type be an int.

AFAICT, that's just not going to work here.


What am I missing?

Alf P. Steinbach

unread,
Nov 26, 2009, 6:34:55 PM11/26/09
to
* James:

Difficult to say since you haven't made your design requirements very clear.

But in general you can't portably deduce function result types in C++98 without
"registering" all relevant types first (you can however do that in C++0x).

Anyway, perhaps this helps:


<code>
#include <stdio.h>

template< typename Result >
class AbstractInvokable
{
public:
virtual Result operator()() const = 0;
};

template< typename Result, typename Arg >
class Invokable
: public AbstractInvokable< Result >
{
private:
Arg myArg;
Result (*myF)( Arg );
public:
Invokable( Result f( Arg ), Arg a )
: myArg( a )
, myF( f )
{}

virtual Result operator()() const
{
return myF( myArg );
}
};

template< typename Result, typename Arg >
Invokable< Result, Arg > bind( Result f( Arg ), Arg a )
{
return Invokable< Result, Arg >( f, a );
}


int foo( int x ) { return printf( "f(%d)\n", x ); }
void blah( char const* s ) { printf( "blah(\"%s\")\n", s ); }

int main()
{
AbstractInvokable<int> const& f = bind( foo, 42 );
AbstractInvokable<void> const& b = bind( blah, "whoopie doo!" );

f();
b();
}
</code>

Frank Neuhaus

unread,
Nov 27, 2009, 4:18:34 AM11/27/09
to

"James" <n...@spam.invalid> schrieb im Newsbeitrag
news:hen1lk$t8r$1...@aioe.org...

This works for me:

#include <iostream>
#include <boost/type_traits.hpp>
#include <boost/typeof/typeof.hpp>

int foo()
{
return 0;
}

int main()
{
typedef boost::function_traits<BOOST_TYPEOF(foo)>::result_type result_type;
result_type test=5;
std::cout << test << std::endl;
}

Michael Tsang

unread,
Nov 27, 2009, 7:00:58 AM11/27/09
to
James wrote:

Use the new function declaration syntax e.g.

template<class t, class u> auto func(const T &t, const U &u) -> decltype(t *
u);

James

unread,
Nov 27, 2009, 1:34:17 PM11/27/09
to
"Frank Neuhaus" <fneu...@uni-koblenz.de> wrote in message
news:heo5hk$h66$1...@cache.uni-koblenz.de...

>
> "James" <n...@spam.invalid> schrieb im Newsbeitrag
> news:hen1lk$t8r$1...@aioe.org...
[...]

>> What am I missing?
>
> This works for me:
>
> #include <iostream>
> #include <boost/type_traits.hpp>
> #include <boost/typeof/typeof.hpp>
>
> int foo()
> {
> return 0;
> }
>
> int main()
> {
> typedef boost::function_traits<BOOST_TYPEOF(foo)>::result_type
> result_type;
> result_type test=5;
> std::cout << test << std::endl;
> }

Thanks. However, I cannot use Boost.

;^(

Anyway, I got this far:


#include <iostream>


int const& foo()
{
static int const g_state = 123456;

return g_state;
}


template<typename T> struct func;


template<typename T>
struct func<T()>
{
typedef T result_type;
};


int main(int argc, char *argv[])
{
typedef func<typeof(foo)>::result_type result_type;

result_type x = foo();

std::cout << x << std::endl;

return 0;
}


This works. Unfortunately, it uses a non-portable compiler extension. I
guess I should dig into the source code for BOOST_TYPEOF and try to see how
it maintains portability.

James

unread,
Nov 27, 2009, 1:56:25 PM11/27/09
to
"James" <n...@spam.invalid> wrote in message news:hep61d$idb$1...@aioe.org...

> "Frank Neuhaus" <fneu...@uni-koblenz.de> wrote in message
> news:heo5hk$h66$1...@cache.uni-koblenz.de...
>>
>> "James" <n...@spam.invalid> schrieb im Newsbeitrag
>> news:hen1lk$t8r$1...@aioe.org...
> [...]
>>> What am I missing?
>>
>> This works for me:
>>
>> #include <iostream>
>> #include <boost/type_traits.hpp>
>> #include <boost/typeof/typeof.hpp>
>>
>> int foo()
>> {
>> return 0;
>> }
>>
>> int main()
>> {
>> typedef boost::function_traits<BOOST_TYPEOF(foo)>::result_type
>> result_type;
>> result_type test=5;
>> std::cout << test << std::endl;
>> }
>
> Thanks. However, I cannot use Boost.

BTW, how in the heck does Boost get BOOST_TYPEOF to work on MSVC? This is
amazing to me.

Alf P. Steinbach

unread,
Nov 27, 2009, 10:26:19 PM11/27/09
to
* James:

As I recall it uses a trick found by a Russian, based on some half-documented
language extension.

0 new messages