7

I have this situation:

#include <vector>

template<typename T>
T f() { return T(); }

template<>
template<typename T>
std::vector<T> f<std::vector<T>>() {
    return { T() };
}

int main(){
    f<std::vector<int>>();
}

I'm trying to specialize the template for std::vector<T>, but I'm getting this error:

error: too many template-parameter-lists

std::vector<T> f<std::vector<T>>() {

How can I specialize for std::vector<T>?

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
João Paulo
  • 6,300
  • 4
  • 51
  • 80
  • 2
    Partial specialisation for template functions is not allowed. – Mansoor May 20 '19 at 13:38
  • That the case I prefer tag dispatching: `template<>struct Tag{}; template T f(tag) {/*..*/} template std::vector f(tag>) {/*..*/}` – Jarod42 May 20 '19 at 14:46

2 Answers2

10

There's no such thing as partially specialized function templates. What you are doing is creating a new template, so the correct syntax would be:

template<typename T>
std::vector<T> f() {
    return { T() };
}

This overloads the function name f and the two templates are independent. But by having both overloads will make almost all calls to f ambiguous including the one example in your main().

EDIT:

Had you removed the template<> line which would be invalid for class partial specializations too then clang generates more helpful error message:

error: non-class, non-variable partial specialization f<std::vector<T,std::allocator<_Tp1> > > is not allowed

std::vector<T> f<std::vector<T>>() {
Quimby
  • 17,735
  • 4
  • 35
  • 55
6

If a problem is X, and a solution is Y, then usually specialization of function templates is Z. That's when specialization is possible anyway. You can't partially specialize function templates, only overload them.

A solution here would be to use a helper. A class template, which you can specialize, that will do the work. Meanwhile the function template only forwards to it.

namespace detail {
    template<typename T>
    struct f {
        static T work() { return T(); }
    };

    template<typename T>
    struct f<std::vector<T>> {
        static std::vector<T> work() { return {T()}; }
    };
}

template<typename T>
T f() { return detail::f<T>::work(); }
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458