This link doesn't answer my question so I'll ask it here:
Basically I want to write a template function
template <typename Out, typename In>
Out f(In x);
Here I always need to specify Out
when calling f
. I don't want to do it every time, so I basically want
template <typename Out = In, typename In>
Out f(In x);
Which means if I don't specify Out
, it will default to In
. However, this is not possible in C++11.
So my question is, is there any way to achieve the effect:
f(t)
will instantiate f<T,T>(t)
or more generally f<typename SomeThing<T>::type, T>
f<U>(t)
will instantiate f<U, T>(t)
I have a PERFECT solution here! f<const int&>
won't work because a function can't return a reference to a temporary, not related to the techniques used here.
[hidden]$ cat a.cpp
#include <iostream>
#include <type_traits>
#include <typeinfo>
using namespace std;
template <typename Out, typename In>
Out f_impl(In x) {
cout << "Out=" << typeid(Out).name() << " " << "In=" << typeid(In).name() << endl;
return Out();
}
template <typename T, typename... Args>
struct FirstOf {
typedef T type;
};
template <typename T, typename U>
struct SecondOf {
typedef U type;
};
template <typename... Args, typename In>
typename enable_if<sizeof...(Args) <= 1, typename FirstOf<Args..., In>::type>::type f(In x) {
typedef typename FirstOf<Args..., In>::type Out;
return f_impl<Out, In>(x);
}
template <typename... Args, typename In>
typename enable_if<sizeof...(Args) == 2, typename FirstOf<Args...>::type>::type f(In x) {
typedef typename FirstOf<Args...>::type Out;
typedef typename SecondOf<Args...>::type RealIn;
return f_impl<Out, RealIn>(x);
}
int main() {
f(1);
f(1.0);
f<double>(1);
f<int>(1.0);
f<int>(1);
f<const int>(1);
f<int, double>(1);
f<int, int>(1);
f<double, double>(1);
}
[hidden]$ g++ -std=c++11 a.cpp
[hidden]$ ./a.out
Out=i In=i
Out=d In=d
Out=d In=i
Out=i In=d
Out=i In=i
Out=i In=i
Out=i In=d
Out=i In=i
Out=d In=d