Determining function return types for std::function

I'm using the boost::units library (boost::units) and trying to make use of auto and decltype to deal with all the complicated types it produces.

I have a templated function to integrate a mathematical function (which might accept x values with units such as 1*metre) between two points:

template <class Out, class In >
auto integrate( std::function<Out(In)> const & f,
In xmin, In xmax, int nSteps)
-> decltype( f(xmin)  * xmin  )


Now I want to use this with some functions that have big ugly return types. I have written this:

//Standard quantities
quantity<temperature> stdBlackBodyTemp = 2857.0*kelvin;
auto luminousEfficiency = quantity<luminous_flux>(682.0*lumen) / quantity<power>(1.0 * watt);

//Integration range
quantity<length> minWavelength(150.0 * nano * metre);
quantity<length> maxWavelength(600.0 * nano * metre);

//Get type for spectral_differential_current
quantity<length> fakeLength(300.0 * nano * metre);

* plancklaw(fakeLength, stdBlackBodyTemp)) sdctype;

//Define spectral_different_current function
std::function< sdctype(quantity<length>)>
spectral_differential_current = [&stdBlackBodyTemp](quantity<length> l)
{
return
};

//Integrate over spectral_differential_current
auto differential_current = integrate( spectral_differential_current,
minWavelength, maxWavelength, 100);


To define my std::function spectral_differential_current which I'm going to give to integrate I need to know the return type. The only way I have found to get this is by using the function on some random value (fakeLength) and then using decltype. It seems odd that I have to introduce a variable which isn't actually used just to get a type. Is there a better way of approaching this?

-
You could re-use minWavelength instead of introducing fakeLength. Since there could be multiple pmt_radiant_sensitivity and plancklaw with different return types, I'm not sure what you'd expect without giving the input type – and decltype has been constructed to take a standard expression, not some new syntax that only gets types and functions. –  Christopher Creutzig Mar 7 '13 at 12:51
Thanks. I see your point that the return type can't be deduced without the arguments. Is there a better approach I could have taken? I've seen comments in other places suggesting that std::function is really only meant for very specific circumstances. Is this one of them or could my integrate function accept something else? –  paco_uk Mar 7 '13 at 20:11

I'm not sure why you need the typedef in the first place. Is there anything wrong with auto spectral_differential_current = ...?

On a similar note, why do you want to require that f is an std::function, disallowing reasonable calls like integrate(sin, 0, 2, 10)? Most code of this type can happily accept anything that can be called:

template <typename F, typename In>
auto integrate(F f, In xmin, In xmax, int nSteps)
-> decltype(f(xmin)  * xmin)


The compiler will tell you whether a given f is OK. Usually by not finding a suitable integrate function – SFINAE.

Also note the use of typename – that's just a stylistic thing of course, but e.g., double is not a class, so I prefer not to say class for template parameters that would accept a double or a plain function pointer.

-
Thanks, that works! I didn't realise you could directly assign a lambda to a variable without wrapping it in a std::function. I've taken your typename advice as well. –  paco_uk Mar 8 '13 at 11:30