deducing the return type of a function call...

J

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

:^(
 
M

Marcel Müller

James said:
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
 
A

Alf P. Steinbach

* 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
 
J

James

A

Alf P. Steinbach

* James:
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?

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>


Cheers & hth.,

- Alf
 
F

Frank Neuhaus

James said:
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?

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;
}
 
M

Michael Tsang

James said:
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!

:^(

Use the new function declaration syntax e.g.

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

James

Frank Neuhaus said:
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.
 
A

Alf P. Steinbach

* James:
James said:
Frank Neuhaus said:
news:[email protected]... [...]
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.

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


Cheers & hth.,

- Alf
 

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
473,955
Messages
2,570,117
Members
46,705
Latest member
v_darius

Latest Threads

Top