I have the following problem that I just don't see a proper solution to (and maybe there is none): I have a templated method where the return type is dependent on the input type, and thanks to C++11 decltype
the return type can be derive easily, but I would also like to allow the user to define the return type explicitly if desired.
More formally I have a templated function f
, that I would like to be callable as f(x)
, with neither input nor return type explicitly defined. And I would also like to be able to call it as f<ret_t>x()
with the return type explicitly defined, but the input type still derived automatically.
Now, satisfying the first constraint with C++11 is easy (let's assume there's another templated method :
template<typename InT>
auto f(const InT& in) -> decltype(/* code deriving the return type using in */);
But this will not allow overriding of the return type, for that I would have to add it as a second template parameter and move the decltype
derivation into the template definition and probably need to use std::declval<InT>
or std::result_of
:
template<
typename InT,
typename RetT = /* code deriving return type using InT and declval/result_of */>
RetT f(const InT& in);
However, this way I always need to also explicitly define InT
when calling f
. So the declaration of f
in order to be able to leave InT
open but specify RetT
should be:
template<
typename RetT = /* code deriving return type using InT and declval/result_of */,
typename InT>
RetT f(const InT& in);
But since at the point where I need to specify a default value for RetT
, InT
is not yet available and hence cannot be used.
The best workaround I could come up with so far, which is not very satisfying and doesn't seem to work anyway since deduction of RetT
fails (apparently due to the fact that you cannot deduce the types from default arguments), is:
template<typename RetT, typename InT>
RetT f(
const InT& in,
const RetT& = std::declval</* code deriving return type using InT or in and declval/result_of */>());
Are there any better ways to have a default value for RetT
that is dependent on InT
while still being able to explicitly specify RetT
if desired? It's important to note that the return type needs to be available in the function implementation in order for the object of RetT
to be allocated directly and only once inside the method body.
You can use std::conditional
and a dummy
type to check if the function has automatic deduced type or user selected type.
If the user explicitly selects a return type, the return type will be something different from the dummy
type and this will be the return type of the function. Otherwise just use the deduced type as before.
Following one example of usage:
#include <typeindex>
#include <type_traits>
#include <iostream>
struct dummy
{
};
template<typename RetType = dummy, typename T>
auto f(const T& in)
-> typename std::conditional<std::is_same<RetType, dummy>::value, T, RetType>::type
{
std::cout<<typeid(RetType).name()<<" "<<typeid(T).name()<<std::endl;
return in;
}
int main()
{
f(1);
f<float>(1);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With