Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template parameter default to a later one

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:

  1. calling f(t) will instantiate f<T,T>(t) or more generally f<typename SomeThing<T>::type, T>
  2. calling f<U>(t) will instantiate f<U, T>(t)
like image 358
Kan Li Avatar asked Jan 24 '13 19:01

Kan Li


1 Answers

You probably never want to specify In but rather have it deduced, right?

In this case you need to overload the function:

template <typename Out, In>
Out f(In x);

template <typename T>
T f(T x);

Call it:

f(42);
f<float>(42);

… but unfortunately that’s ambiguous for f<int>(42). No matter, we can use SFINAE to disable one of the overloads appropriately:

template <
    typename Out,
    typename In,
    typename = typename std::enable_if<not std::is_same<Out, In>::value>::type
>
Out f(In x);

template <typename T>
T f(T x);

In order to avoid redundancy in the implementation, let both functions dispatch to a common implementation, f_impl.

Here’s a working example:

template <typename Out, typename In>
Out f_impl(In x) {
    std::cout << "f<" << typeid(Out).name() <<
                 ", " << typeid(In).name() <<
                 ">(" << x << ")\n";
    return x;
}

template <
    typename Out,
    typename In,
    typename = typename std::enable_if<not std::is_same<Out, In>::value>::type
>
Out f(In x) {
    std::cout << "f<Out, In>(x):\t ";
    return f_impl<Out, In>(x);
}

template <typename T>
T f(T x) {
    std::cout << "f<T>(x):\t ";
    return f_impl<T, T>(x);
}


int main() {
    f(42);
    f<float>(42);
    f<int>(42);
}
like image 92
Konrad Rudolph Avatar answered Sep 18 '22 19:09

Konrad Rudolph