What is the correct template syntax for this?

F

fabio_cannizzo

The following syntax cause gcc to complain about:
- explicit specialization in non-namespace scope
- enclosing class templates are not explicitly specialized

So I guess that I need to put the specialization of foo<0> somewhere
out of the class definition, but what is the correct syntax to do
that?

Thanks a lot

template <class A>
class MyClass
{
template <unsigned char N>
void foo( sie_t int ) { /* ... */ }

template <>
void foo<0>( sie_t int ) { /* ... */ }
};
 
F

fabio_cannizzo

In the previous messages there where a few typo. I rewrote better the
code:

template <class A>
class MyClass
{
template <unsigned char N>
void foo( int x )
{
// ... do something
foo<N-1>( x );
}

template <>
void foo<0>( int x )
{
// do nothing: stops template expansion recursion
}
};
 
S

SG

The following syntax cause gcc to complain about:
- explicit specialization in non-namespace scope
- enclosing class templates are not explicitly specialized

So I guess that I need to put the specialization of foo<0> somewhere
out of the class definition, but what is the correct syntax to do
that?

Yes. Have you tried the namespace scope? :p

struct S
{
template<int N>
void foo(int k);
};

template<int N>
void S::foo(int k) {}

template<>
void S::foo<0>(int k) {}


Cheers!
SG
 
Z

ZikO

SG said:
Yes. Have you tried the namespace scope? :p

struct S
{
template<int N>
void foo(int k);
};

template<int N>
void S::foo(int k) {}

template<>
void S::foo<0>(int k) {}


Cheers!
SG

Is this also possible for the template function in the template class ?

Cheers!
ZikO
 
S

SG

Is this also possible for the template function in the template class ?

You mean "function template" and "class template". The answer is
yes. It's something along the lines of

template<typename T>
template<int N>
void S<T>::foo(int k) {}

template<typename T>
template<>
void S<T>::foo<0>(int k) {}


Cheers!
SG
 
F

fabio_cannizzo

I tried what suggested in SG's mail, but did not work.

I think specialization of method is not allowed.

Anyway, since the class had not that many members, I changed my design
putting the second template argument in the outer class. Then it
became easy to specialise it.
 
Z

ZikO

SG said:
You mean "function template" and "class template".
Yes. I meant that.
yes. It's something along the lines of

template<typename T>
template<int N>
void S<T>::foo(int k) {}

template<typename T>
template<>
void S<T>::foo<0>(int k) {}

I have tried something as below:

//------------------------------------
#include <iostream>
template<class T> class A {
public:
template<size_t N> void f();
};
template<class T> template<size_t N> void A<T>::f() {
std::cout << N << std::endl;
}
template<class T> template<> void A<T>::f<0>() {
std::cout << "Stopping ..." << std::endl;
}
int main() {
A<int> a;
a.f<10>();
a.f<0>();
}
//------------------------------------

test2.cpp:10: error: invalid explicit specialization before '>' token
test2.cpp:10: error: enclosing class templates are not explicitly
specialized
test2.cpp:10: error: template-id 'f<0>' for 'void A<T>::f()' does not
match any template declaration


Well, as I found there was no matching f<0> to anything, I added
declaration in the class template, so appart from the class definition,
everything looks the same in the code:

//-------------------------------------
#include <iostream>
template<class T> class A {
public:
template<size_t N> void f();
template<> void f<0>();
};
template<class T> template<size_t N> void A<T>::f() {
std::cout << N << std::endl;
}
template<class T> template<> void A<T>::f<0>() {
std::cout << "Stopping ..." << std::endl;
}
int main() {
A<int> a;
a.f<10>();
a.f<0>();
}
//-------------------------------------

but it looks even worse:
test2.cpp:6: error: explicit specialization in non-namespace scope
'class A<T>'
test2.cpp:11: error: invalid explicit specialization before '>' token
test2.cpp:11: error: enclosing class templates are not explicitly
specialized
test2.cpp:11: error: template-id 'f<0>' for 'void A<T>::f()' does not
match any template declaration

So what do you think I am doing wrong here?


Cheers!
Ziko
 
S

SG

I tried what suggested in SG's mail, but did not work.
I think specialization of method is not allowed.

I haven't tested member function specialization of a class template
and I thought it was supposed to work. Sorry for the trouble.

As a rule of thumb you should try to avoid specializing function
templates altogether. There are other alternatives (like overloading
function templates or turning a function template into a non-templated
member function of some class template).


Cheers!
SG
 
T

Triple-DES

You mean "function template" and "class template".  The answer is
yes.  It's something along the lines of

   template<typename T>
   template<int N>
   void S<T>::foo(int k) {}

   template<typename T>
   template<>
   void S<T>::foo<0>(int k) {}

The second example is ill-formed. A member template can not be
explicitly (fully) specialized unless the enclosing class template is
also explicitly (fully) specialized.

template<>
template<>
void S<int>::foo<0>(int k) {} // ok

template<>
template<int N>
void S<int>::foo<0>(int k) {} // ok

template<typename T>
template<>
void S<T>::foo<0>(int k) {} // ill-formed
 
A

Andrey Tarasevich

The following syntax cause gcc to complain about:
- explicit specialization in non-namespace scope
- enclosing class templates are not explicitly specialized

So I guess that I need to put the specialization of foo<0> somewhere
out of the class definition, but what is the correct syntax to do
that?

Thanks a lot

template <class A>
class MyClass
{
template <unsigned char N>
void foo( sie_t int ) { /* ... */ }

template <>
void foo<0>( sie_t int ) { /* ... */ }
};

There's no immediate correct syntax for this. Explicit specialization of
a member template without explicit specialization of enclosing template
is not allowed in C++.

If the inner template was a class template, you could've worked around
this limitation by introducing a dummy parameter and using partial
specialization instead of explicit one. So, you can try wrapping your
'foo' into a class (as a static member) and applying this workaround

template <class A>
class MyClass
{
template <unsigned char N, unsigned char DUMMY = 0>
struct S
{
static void foo( int x ) { /* ... */ }
};

template <unsigned char DUMMY>
struct S<0, DUMMY>
{
static void foo( int x ) { /* ... */ }
};
};

This looks like workaround on workaround, and is generally ugly, but it
works.
 
M

Martin Eisenberg

The following syntax cause gcc to complain about:
- explicit specialization in non-namespace scope
- enclosing class templates are not explicitly specialized

Here's another workaround:

#include <iostream>

template <int i>
struct int_ { static const int value = i; };

// or #include <boost/mpl/int.hpp>

template <class A>
class MyClass {
private:
template <int N>
void foo(int x, int_<N>)
{
std::cout << N << ',';
foo(x, int_<N-1>());
}
// note overload, not specialization
void foo(int x, int_<0>)
{ std::cout << " x = " << x; }
public:
template <unsigned char N>
void foo(int x) { foo(x, int_<N>()); }
};

int main()
{
MyClass<float> m;
m.foo<3>(5);
return 0;
}


Martin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top