Using MSVC++ 2010, defining a templated class member outside its declaration block:
template <typename T> class cls {
public:
template <typename T> void bar(T x);
};
template <typename T> void cls<T>::bar(T x) {}
yields:
unable to match function definition to an existing declaration
1> definition
1> 'void cls<T>::bar(T)'
1> existing declarations
1> 'void cls<T>::bar(T)'
why?
You need two template declarations because each construct works on a different template argument:
template <typename P>
template <typename T>
void cls<P>::bar(T x) {}
But it seems to me that bar does not need to be templated at all. Use this instead:
template <typename T>
class cls
{
public:
void bar(T x);
};
template <typename T> void cls<T>::bar(T x) {}
If you're intention is for bar to be a member template, then you need this:
template <typename T> class cls {
public:
template <typename U> void bar(U x);
};
template<typename T>
template<typename U>
void cls<T>::bar(U x) { }
Note that, the template parameter of the member must not shadow the class template parameter, hence I changed it to U.
Related
I'm not sure if what I'm trying to do is possible. Here's an example:
template <typename T>
class Ref
{
void Decrement();
};
template <typename T>
class Collection {};
// This will error
template <>
template <typename T>
void Ref<Collection<T>>::Decrement() {}
You can't specialize just one function inside a class template; you have to specialize the class template as a whole.
template <typename T>
class Ref
{
void Decrement();
};
template <typename T>
class Collection {};
template <typename T>
class Ref<Collection<T>> {
void Decrement() {}
};
You can specialize a function template inside a class, i.e., this:
class Ref {
template <typename U> void Decrement();
};
or a function template inside a class template...
template <typename T>
class Ref {
template <typename U> void Decrement();
};
However, even then, a partial specialization, which is what you want to do, cannot be done for a function template; function templates can only be fully specialized for individual types, and never partially specialized, whereas class templates can be either partially or fully specialized.
I have the following nested template
class A {
template <typename T> class B {
template <typename U> void foo(U arg);
};
};
I am trying to define the nested template like so:
template <typename T, typename U> void
A::B<T>::foo(U arg) {...}
But am getting declaration is incompatible with function template error. What's the legal syntax to do so?
You need to separate the template declarations:
template <typename T>
template <typename U>
void
A::B<T>::foo(U arg) { … }
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:
Why Not Specialize Function Templates?
Template Specialization and Overloading
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);
}
Environment: Microsoft Visual Studio 2010
Coding standard: C++0x compatible
I have a class template
template <typename T1, int I>
class A
{
public template <typename T2> void f(T2 x);
/*...*/
};
template <typename T1, int I>
template <typename T2>
void A<T1, I>::f(T2 x)
{
/*...*/
}
and partial specialization of above class
template <int I>
class A<char, I>
{
public template <typename T2> void f(T2 x);
/*...*/
};
Then can I specialize member function in the partially specialized class like below?
template <int I>
template <>
void A<char, I>::f<double>(double x)
{
}
Thanks!
NB: I'm not working on it but thinking if it's applicable or not. Easy rating if you know about the rule.
This is invalid because you cannot explicitly specialize a member function without also giving fixed template arguments to any enclosing class template.
Not C++11 compatible, but working on MSVC
The Microsoft compiler has an extension that allows to declare explicit specializations within class templates though. Even though I have never tried it, chances are good that it will accept the following non-standard code
template <int I>
class A<char, I>
{
public:
template <typename T2> void f(T2 x);
template<> void f<double>(double x) {
}
/*...*/
};
Update: Clang compiles this and reports
// clang++ -fms-extensions main1.cpp
main1.cpp:10:21: warning: explicit specialization of 'f' within class scope is a
Microsoft extension [-Wmicrosoft]
template<> void f<double>(double x) {
^
C++11/C++03 compatible
The way here is overloading instead of specialization
template <int I>
class A<char, I>
{
public:
template <typename T2> void f(T2 x);
void f(double x) {
}
/*...*/
};
I got trouble in creating special instance of member template function of non-template class. I have, for example, class A with template member function F:
class A
{public:
template <class T> int F (T arg) const;
....
}
and want to have a special instance of this template function F for type B:
class B;
...
template <> void A::F (B arg) const //GOOD!
and it works perfectly, until appears that B is a template itself!
This code
template <class T> class B ...
...
template <> void A::F (B<T> arg) const //error, T undeclared
as well as
template <class T> class B ...
...
template <class T> template <> void A::F (B<T> arg) const //error, too many templates
gives compiling error.
The second trouble is, how to declare this special instance (or template instance at whole) to be friend function of class B? (Is does not work even if B is not a template).
class B
{friend template <> void A::F (B arg) const // error
// as well as
template <> friend void A::F (B arg) const // error
}
Is there a way to write code in a way I'm going to at all or it is not possible?
You're attempting to create a partial specialization for a function template, which is illegal. What you can do is simply create an overload.
To create a friend, you merely have to use the correct syntax.
The following compiles without errors.
template <typename T>
struct B {};
struct A
{
template <typename T>
void F(T arg) const;
template <typename T>
void F(B<T> arg) const;
template <typename T>
friend void G(B<T> arg);
template <typename T>
friend struct B;
};