views:

392

answers:

4

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++?

+1  A: 

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.

JaredPar
What about C++ < C++0x ?
Stefano Borini
Unfortunately you're a bit stuffed with pre-C++0x in this respect. It might be worth looking at boost::any but I don't know if that would work in this context - never tried it.
Timo Geusch
@Stefano: Use The Programmer's All-Purpose Cure: another level of indirection. In this case, as already mentioned in the question, this would be a function template that you call.
sbi
+3  A: 

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

AProgrammer
Seems that VS2008 recognizes the 'auto' keyword (it colors it blue). However, using it yeilds a 'missing type specifier' compiler error. Any idea what it used for in VC?
`auto` is used in existing C++ as a storage class specifier, similar to `static` and `register`, and it's the default for local variables. You can omit it and have the same meaning.
Johannes Schaub - litb
@sold auto is an existing keyword it C++ which is being re-used. It dates back to days of B I believe. Can't remember off the top of my head what it was originally used for.
JaredPar
http://msdn.microsoft.com/en-us/library/6k3ybftz.aspx -- it's part of the C and today C++'s standard, but not very useful in its meaning of today;-).
Alex Martelli
@JaredPar, its redundant with the absence of `static` in function and forbidden elsewhere. It has no use excepted symmetry.
AProgrammer
Note for the historians: register is absent of B (according to http://cm.bell-labs.com/cm/cs/who/dmr/bref.pdf) and present in C in 1975 (http://cm.bell-labs.com/cm/cs/who/dmr/cman.pdf)
AProgrammer
At least, the beloved C++ Standard notes that one can make explicit that a variable is declared instead of a cast-expression evaluated by putting `auto` in-front: `auto int(a);`.
Johannes Schaub - litb
@litb: so "auto int(a);" is equivalent to "int a;", while "int(a);" is just a cast expression with a throw-away result? I hope I never come across that in real code, because I'll never remember that.
Michael Burr
@Michael, when there is an ambiguity between a declaration and an expression, it is a declaration. So the auto just clarify the situation, it doesn't not change the meaning.
AProgrammer
+2  A: 

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;
  }
}
J.F. Sebastian
+2  A: 

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));
UncleBens
I'm generally aware of these conventions - at least at a basic level. But it seems like one has to learn these things by repeated experience with STL, other well-written template libraries and by reading Josuttis and Vandevoorde's' Template book. Is there a simple list of these idiomatic typedefs anywhere? That way I'll know what I should make sure is in any template I write, not to mention know to use them.
Michael Burr