Reputation:
I need to use a function's/functor's returned value without knowing what type it is (that is, as a template).
While I could pass it over to a second function without a problem:
template <typename T>
void DoSomething(T value);
...
DoSomething(FunctionWhoseReturnedTypeIsUnknown(...));
I want to use the returned value inline (without the need to call a second function):
WhatGoesHere? x=FunctionWhoseReturnedTypeIsUnknown(...);
The two methods seem conceptually identical to me (generic-programming-wize), but can the latter be achived in C++?
Upvotes: 3
Views: 2528
Reputation: 943
This is really late, but I was trying to figure out how to do this and ran into this question. The environment I'm using can't use C++11 (aka C++0x) or Boost, although both of those are awesome, so I figured I'd post how I figured out to do this without either for the sake of posterity.
As UncleBens alluded to, the functional header in the STL has some useful features if you aren't using C++11 or Boost: http://www.cplusplus.com/reference/std/functional/
This problem is a bit more general than just not wanting to call a second template function. For example, one might want to build a vector of the return type of a functor, in which case calling a second template function might not work.
By using some function overloading (to operate on both function pointers and functors) and stl's , we can make this work. Here's an example that prints out the result of a one-argument functor/function argument after declaring the variable explicitly:
#include <iostream>
#include <functional>
using namespace std;
// Simple function [pointer] that adds one to its argument
int addOne(int n)
{
return n + 1;
}
// Simple functor that multiplies its argument by two
class timesTwo
{
public:
int operator()(int n) const { return n * 2; }
};
// Simple higher-order function: takes a functor f and calls f on n, returning the result
// This is your template function in which you want to know the return type of f
template <typename Functor>
void printResultImpl(Functor f, typename Functor::argument_type n)
{
typename Functor::result_type r = f(n);
cout << r << endl;
}
// Wrapper function for function pointer
template <typename Arg, typename Result>
void printResult(Result (*f)(Arg), Arg n)
{
printResultImpl(ptr_fun(f), n);
}
// Wrapper function for functor (function object)
template <typename Functor, typename Arg>
void printResult(Functor f, Arg n)
{
printResultImpl(bind1st(mem_fun(&Functor::operator()), &f), n);
}
// Prints out 8 then 14
int main()
{
printResult(addOne, 7);
printResult(timesTwo(), 7);
}
There are a couple limitations to this method: 1. You can't have your function return the result type of the functor (since the wrapper function doesn't know the result type) 2. It relies upon unary_function or binary_function in the stl. As UncleBens demonstrated, it's possible to extend to other types - simply follow the pattern of the declarations in : http://www.cplusplus.com/reference/std/functional/
But it worked for what I needed; maybe it'll work for someone else.
Upvotes: 1
Reputation: 41351
Until the auto keyword makes it really trivial, one can rely on the convention that function objects provide certain typedef's, including result_type. One just needs to wrap a plain function into a function object. The standard "functional" header provides some (pointer_to_unary_function/pointer_to_binary_function in addition to a couple of member function wrappers). When these are not enough, boost library provides more powerful wrappers.
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
int answer()
{
return 42;
}
template <class T>
T unknown()
{
return T();
}
template <class Function>
void foobar(Function unknown)
{
typename Function::result_type x = unknown();
std::cout << x << '\n';
}
int main()
{
foobar(boost::function<int()>(answer));
foobar(boost::bind(unknown<int>));
}
And below's an example, how you might add a pointer_to_zeronary_function. (I suppose the helper function that helps you create one, ptr_fun, might be added to the standard namespace as well as an overload(?)
template <class T>
class pointer_to_zeronary_function
{
typedef T(*zeronary_func)();
zeronary_func func;
public:
typedef T result_type;
pointer_to_zeronary_function(zeronary_func f): func(f) {}
T operator()() const
{
return func();
}
};
template <class T>
pointer_to_zeronary_function<T> ptr_fun(T(*f)())
{
return pointer_to_zeronary_function<T>(f);
}
...
//usage:
foobar(ptr_fun(answer));
Upvotes: 5
Reputation: 414905
It depends on your specific use case but sometimes boost::any can be used:
#include <iostream>
#include <boost/any.hpp>
namespace {
template <class T>
T return_arg(T t) {
return t;
}
}
int main() {
try {
boost::any i = return_arg(1);
boost::any s = return_arg("a string");
std::cout << boost::any_cast<int>(i) << " "
<< boost::any_cast<const char*>(s)
<< std::endl;
}
catch(const boost::bad_any_cast &) {
return 1;
}
}
Upvotes: 2
Reputation: 52334
Not yet. In C++0X you'll be able to use auto
as WhatGoesHere
. There is already experimental support for this in some compilers (gcc 4.4 for instance).
Upvotes: 5
Reputation: 755587
C++0x introduces the concept of an inferred variable type by using the keyword auto.
auto x = SomeFunction();
The result is the same as C#'s var keyword: a strongly typed variable whose type is the return type of the expression.
In the absence of C++0x there is no good way to achieve this outside of a template. If there ways, C++0x would have no need for this feature.
Upvotes: 2