Partial but not full/explicit specialization at non-namespace scope.

F

Ferdi Smit

I've never understood the rationale of allowing partial, but not
explicit specialization for classes at non-namespace scope. Ie.:

struct A {
template <typename T1, typename T2>
struct B {};

// this is not allowed:
template <>
struct B<int, float> {};

// but this IS:
template <typename T2>
struct B<int, T2> {};
};

What is the reason for this rule?
 
D

Dan Cernat

Ferdi said:
I've never understood the rationale of allowing partial, but not
explicit specialization for classes at non-namespace scope. Ie.:

struct A {
template <typename T1, typename T2>
struct B {};

// this is not allowed:
template <>
struct B<int, float> {};

// but this IS:
template <typename T2>
struct B<int, T2> {};
};

What is the reason for this rule?

VC++ 7.1 the code below compiles

struct A {
template <typename T1, typename T2>
struct B {};

template <>
struct B<int, float> {};

template <typename T2>
struct B<int, T2> {};
};

int main()
{
A a;
A::B<char, char> b1;
A::B<int, float> b2;
A::B<int, char> b3;

return 0;
}

so I guess it is time to change compilers.

dan
 
V

Victor Bazarov

Ferdi said:
I've never understood the rationale of allowing partial, but not
explicit specialization for classes at non-namespace scope. Ie.:

struct A {
template <typename T1, typename T2>
struct B {};

// this is not allowed:
template <>
struct B<int, float> {};

// but this IS:
template <typename T2>
struct B<int, T2> {};
};

What is the reason for this rule?

I strongly recommend asking about rationales in comp.std.c++. Here we
talk the "how", there they discuss the "why".

V
 
G

Greg Comeau

VC++ 7.1 the code below compiles

struct A {
template <typename T1, typename T2>
struct B {};

template <>
struct B<int, float> {};

template <typename T2>
struct B<int, T2> {};
};

int main()
{
A a;
A::B<char, char> b1;
A::B<int, float> b2;
A::B<int, char> b3;

return 0;
}

so I guess it is time to change compilers.

Comeau C++ will also compile the above code.

However, it will only do it in our VC++ compatibility mode,
because in standard mode it is an error:

Comeau C/C++ 4.3.4.1 (Mar 30 2005 22:54:12) for MS_WINDOWS_x86
Copyright 1988-2005 Comeau Computing. All rights reserved.
MODE:strict errors C++

"it2.cpp", line 5: error: explicit specialization is not allowed in the
current scope
template <>
^

This is as per Standard C++, since that line can't be in class scope.

So I guess it is time to change compilers :)
 
D

Dan Cernat

Greg said:
Ferdi Smit wrote:
[snip]
VC++ 7.1 the code below compiles
[snip again]
Comeau C++ will also compile the above code.

However, it will only do it in our VC++ compatibility mode,
because in standard mode it is an error:

Comeau C/C++ 4.3.4.1 (Mar 30 2005 22:54:12) for MS_WINDOWS_x86
Copyright 1988-2005 Comeau Computing. All rights reserved.
MODE:strict errors C++

"it2.cpp", line 5: error: explicit specialization is not allowed in the
current scope
template <>
^

This is as per Standard C++, since that line can't be in class scope.

So I guess it is time to change compilers :)

LOL

Thanks, Greg.
 
G

Greg Comeau

Greg said:
Ferdi Smit wrote:
[snip]
VC++ 7.1 the code below compiles
[snip again]
Comeau C++ will also compile the above code.

However, it will only do it in our VC++ compatibility mode,
because in standard mode it is an error:

Comeau C/C++ 4.3.4.1 (Mar 30 2005 22:54:12) for MS_WINDOWS_x86
Copyright 1988-2005 Comeau Computing. All rights reserved.
MODE:strict errors C++

"it2.cpp", line 5: error: explicit specialization is not allowed in the
current scope
template <>
^

This is as per Standard C++, since that line can't be in class scope.

So I guess it is time to change compilers :)

LOL

Thanks, Greg.

BTW, the reason, at least as I recall it (so I could be wrong
and/or recalling it wrong), was "simply" that it was not known if
allowing it that way would be beneficial, and since allowing
a more liberal structure was considered to be a possible
implementation burden upon implementators, it was prohibited.
It's come up before about relaxing that, especially in combo
with other prohibitions.
 
F

Ferdi Smit

Dan Cernat said:
VC++ 7.1 the code below compiles
[snip]
so I guess it is time to change compilers.

Yes, I know, perhaps I ought to have mentioned that. Anyway, not trying to
bash anyone, but VC7.1 is not a very good compiler to test these matters
with. I've found numerous of similar, wrong "features" concerning templates;
even in strict mode. But thanks for your time in trying to compile it for
me, it's appreciated :)
 
F

Ferdi Smit

Greg Comeau said:
BTW, the reason, at least as I recall it (so I could be wrong
and/or recalling it wrong), was "simply" that it was not known if
allowing it that way would be beneficial, and since allowing
a more liberal structure was considered to be a possible
implementation burden upon implementators, it was prohibited.
It's come up before about relaxing that, especially in combo
with other prohibitions.

But isn't partial specialization the more liberal structure? Whenever I
really need explicit specialization in this way, I can simply add a dummy
template parameter :

struct A {
template <typename T, int dummy>
struct B {};

// this is ok, simulating explicit spec. with dummy
template <int dummy>
struct B<float, dummy> {};

// then why is this (or similar without the dummy) not ok?
template <>
struct B<float, 0> {};
};

I've used this to write templated recursion on an integer in the class. As
(member) functions can only be explicitly specialized, adding a dummy
template parameter is not an option there. Another way out is to use an
Int2Type construct (ala alexandrescu/loki) and function overloading...
however, why do I have to resort to these kinds of tricks? To me it doesn't
really make sense, however I might be missing a deeper issue (?)
 
G

Greg

Ferdi said:
But isn't partial specialization the more liberal structure? Whenever I
really need explicit specialization in this way, I can simply add a dummy
template parameter :

struct A {
template <typename T, int dummy>
struct B {};

// this is ok, simulating explicit spec. with dummy
template <int dummy>
struct B<float, dummy> {};

// then why is this (or similar without the dummy) not ok?
template <>
struct B<float, 0> {};
};

I've used this to write templated recursion on an integer in the class. As
(member) functions can only be explicitly specialized, adding a dummy
template parameter is not an option there. Another way out is to use an
Int2Type construct (ala alexandrescu/loki) and function overloading...
however, why do I have to resort to these kinds of tricks? To me it doesn't
really make sense, however I might be missing a deeper issue (?)

All that is missing is a namespace. Declaring A in a namespace lets B
be explicitly instantiated:

namespace N {

struct A
{
template <typename T1, typename T2>
struct B
{
};
};

// explicit instantiation for N::A::B<int, int>
template <>
struct A::B<int, float>
{
}; }

using N::A;

int main()
{
A::B<int, float> a;
}

Why A has to be in a namespace in order for B to be explicitly
instantiated is a bit unclear. But as this example shows, the effect on
the program is otherwise unlikely to be dramatic. And declaring classes
in non-global namespaces is usually a good idea for other reasons.

Greg
 

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,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top