简体   繁体   中英

Specialize templated function for templated class

In C++, I am trying to specialize a templated function for a object that is templated itself.

Here is a basic example: test.h:

template <class T>
class myC {
    T x;
};

template <class U>
void f(U y) {
}

template <>
template <class T>
void f<myC<T> >(myC<T> y) {
}

test.cpp

#include "test.h"
int main() {
    myC<double> m;
    f(m);
}

GCC 4.6.1 gives me the following error message:

In file included from test.cpp:1:0:
test.h:13:25: error: too many template parameter lists in declaration of ‘void f(myC<T>)’
test.h:13:6: error: template-id ‘f<myC<T> >’ for ‘void f(myC<T>)’ does not match any template declaration
test.h:13:25: note: saw 2 ‘template<>’, need 1 for specializing a member function template

Is this at all possible? Or is there another way to accomplish the same goal?

template <>
template <class T>
void f<myC<T> >(myC<T> y) {
}

What you're atttempting to be doing here is called partial specialization which is not allowed in case of function template.

A function template is either fully specialized, or not specialized at all. No partial specialization of function template is allowed by the language specification.

So you can overload the function template as:

template <class T>
void f(myC<T> y)  //note that it is overload, not specialization
{ 
}

which is allowed, and preferred over even fully specialization of template.

Read these articles by Herb Sutter:

You cannot specialize a template function; only template classes can be specialized. Edit: Nawaz's answer is correct: it's partial specialization that is not allowed for template functions, only for classes. A full specialization is possible:

template <class U> void f(U y) {}
template<> void f<double>(double y) {} // specialization for double

Note that the template argument need not be explicitly specified if it can be deduced from the context:

template<> void f<>(int y) {} // specialization for int

In your case, full specialization is not possible because the function argument is a template class. However, a template function, like any function, can be overloaded. In your case, it will be like this:

template <class T>
class myC {
    T x;
};

template <class U>
void f(U y) {
}

template <class T>
void f(myC<T> y) {
}

int main() {
    myC<double> m;
    f(m);
    return 0;
}

As far as I can tell, you cannot specialize template functions, only template classes (or structs).

But that is hardly a limitation: just declare a struct with static public member functions and mave the template parameters to the struct:

template <class T>
class myC {
    T x;
};

template <class U>
struct Foo
{
    static void f(U y) {
    }
};

template <>
template <class T>
struct Foo<myC<T> >
{
    static void f(myC<T> y) {
    }
};

The drawback is that class templates do not solve the template parameters automatically. But that can be easlily solved with a function template, similar to the original one:

template <class U>
void f(U y) {
    return Foo<U>::f(y);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM