Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Explicit Specialization in Non-Namespace Scope

356 views
Skip to first unread message

Terry G

unread,
Nov 10, 2008, 1:26:35 PM11/10/08
to
The following program compiles and works with Visual C++ but not with G++
4.3.0 or G++ 4.4.0.
GCC complains that I'm using "explicit specialization in non-namespace
scope".
Should this work?

terry

template <
int W0=0, int W1=0, int W2=0, int W3=0, int W4=0,
int W5=0, int W6=0, int W7=0, int W8=0, int W9=0
>
class IntArgs {
public:

template <int N> struct Arg { };

template <> struct Arg<0> { static const int value = W0; };
template <> struct Arg<1> { static const int value = W1; };
template <> struct Arg<2> { static const int value = W2; };
template <> struct Arg<3> { static const int value = W3; };
template <> struct Arg<4> { static const int value = W4; };
template <> struct Arg<5> { static const int value = W5; };
template <> struct Arg<6> { static const int value = W6; };
template <> struct Arg<7> { static const int value = W7; };
template <> struct Arg<8> { static const int value = W8; };
template <> struct Arg<9> { static const int value = W9; };

template <int N>
struct Offset {
static const int value = Arg<N-1>::value + Offset<N-1>::value;
}; // Offset

template <> struct Offset<0> { static const int value = 0; };

}; // IntArgs

#include <iostream>
#include <iomanip>
#include <typeinfo>

using namespace std;

int main() {
typedef IntArgs<41, 23, 17, 99> MyInts;
cout << typeid(MyInts).name() << endl;
cout << "MyInts::Arg<2>::value=" << MyInts::Arg<2>::value << endl;
cout << "MyInts::Offset<2>::value=" << MyInts::Offset<2>::value << endl;
return 0;
} // main

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Gil

unread,
Nov 10, 2008, 7:40:51 PM11/10/08
to
MSVC has allowed for a long time now explicit specialization at class
scope.

standard does not.

I think some compilers (Comeau?) even have a flag to mimic
this MSVC 'compatibility', against the standard.

not to mention that people even filed GCC bugs related to the error
'explicit specialization in non-namespace scope':

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34726

read 14.7.3 - Explicit specialization [temp.expl.spec]
especially 14.7.3.2, 14.7.3.17, 14.7.3.18.

14.7.3.2:
-2- An explicit specialization shall be declared in the namespace of
which the template is a member, or, for member templates, in the
namespace of which the enclosing class or enclosing class template is
a member. An explicit specialization of a member function, member
class or static data member of a class template shall be declared in
the namespace of which the class template is a member.

please look at example below, you can see how I moved
the explicit specialization at namespace scope:

// -----------------------------------------

/*
* inner_specialized.cpp
*
* Created on: Nov 10, 2008
* Author: gil
*/


#include <iostream>

struct Outer {
template< int I > struct Inner {
static const int value = Inner< I - 1 >::value;
};
/*
* gcc conforms to standard;
* standard (14.7.3.2) would not allow you to
* explicitly specialize Inner here,
* (but will accept a partial specialization)
*/
/*
template< > struct Inner< 0 > {


static const int value = 0;
};

*/
};

template< >
struct Outer::Inner< 0 > {


static const int value = 0;
};

using namespace std;

int main( ) {
cout << Outer::Inner< 10 >::value << endl;
return EXIT_SUCCESS;
}

// -----------------------------------------

in your example it's easier to add a bogus template parameter to inner
template members and only specialize them partially at class scope.

so standard allows this:

// ---------------------------------------------------

template <
int W0=0, int W1=0, int W2=0, int W3=0, int W4=0,
int W5=0, int W6=0, int W7=0, int W8=0, int W9=0
>
class IntArgs {
public:

template < int N, typename T = void > struct Arg { };

// note the partial vs explicit specialization
template <typename T> struct Arg<0, T> { static const int value =
W0; };
template <typename T> struct Arg<1, T> { static const int value =
W1; };
template <typename T> struct Arg<2, T> { static const int value =
W2; };
template <typename T> struct Arg<3, T> { static const int value =
W3; };
template <typename T> struct Arg<4, T> { static const int value =
W4; };
template <typename T> struct Arg<5, T> { static const int value =
W5; };
template <typename T> struct Arg<6, T> { static const int value =
W6; };
template <typename T> struct Arg<7, T> { static const int value =
W7; };
template <typename T> struct Arg<8, T> { static const int value =
W8; };
template <typename T> struct Arg<9, T> { static const int value =
W9; };

template <int N, typename T = void>
struct Offset {
static const int value = Arg<N-1, T>::value + Offset<N-1,
T>::value;
}; // Offset

// again, using partial specialization at class scope
template <typename T> struct Offset<0, T> { static const int value
= 0; };

}; // IntArgs

// ----------------------------------------------------

with above modifications, compiled with g++ (GCC) 4.1.1,
your test programs displays:

7IntArgsILi41ELi23ELi17ELi99ELi0ELi0ELi0ELi0ELi0ELi0EE
MyInts::Arg<2>::value=17
MyInts::Offset<2>::value=64

cheers,
gil

Terry G

unread,
Nov 11, 2008, 11:01:01 AM11/11/08
to
I already know that there is a workaround using an extra defaulted template
parameter so that the template is partial instead of explicit.
Why should I have to resort to such trickery?
Is there a problem with full specialization within class scope?
Is there a better way?

terry

"Terry G" <tjgo...@netins.net> wrote in message
news:gf9805$8th$1...@news.netins.net...


> The following program compiles and works with Visual C++ but not with G++
> 4.3.0 or G++ 4.4.0.
> GCC complains that I'm using "explicit specialization in non-namespace
> scope".
> Should this work?
>
> terry
>
> template <
> int W0=0, int W1=0, int W2=0, int W3=0, int W4=0,
> int W5=0, int W6=0, int W7=0, int W8=0, int W9=0
>>
> class IntArgs {
> public:
>
> template <int N> struct Arg { };

becomes
template <int N, int Dummy=0> struct Arg { };

>
> template <> struct Arg<0> { static const int value = W0; };

becomes
template <int Dummy> struct Arg<0, Dummy> { static const int value =
W0; };

...

0 new messages