namespace A{
namespace B{
template<typename T>
struct Test{
};
}
using namespace B;
template<>
struct Test<int>{}; //#1
}
int main(){
}
Consider the above code, GCC
complains such code is ill-formed and Clang
consider such code is well-formed. The outcome is here. At #1
, it's an explicit specialization declaration for class template Test
. According to this rule:
temp.expl.spec#2
An explicit specialization may be declared in any scope in which the corresponding primary template may be defined.
The primary template Test
can be defined outside namespace B
, as long as it obeys the following rule:
namespace.memdef#2
Members of a named namespace can also be defined outside that namespace by explicit qualification ([namespace.qual]) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration's namespace.
That is we may define the primary template Test
like this:
namespace A{
namespace B{
template<typename T>
struct Test;
}
template<typename T>
struct B::Test{ // Test is explicit qualified by B
};
}
So, we're permitted to define explicit specialization at such point. However It's unclear that It is necessary to declare such explicit specialization by using qualified-id? However an additional rule is here:
temp.expl.spec#8
A template explicit specialization is in the scope of the namespace in which the template was defined.
So Clang
is wrong? How to interpret such case.
template struct Test
declared innamespace A
beforenamespace B
- whichstruct Test
would you be defining? – 1201ProgramAlarmqualified-id
which containnested-name-specifier
that named enclosing namespace. So, I think it's unclear in the standard. MaybeClang
is right. – xmh0511using namespace B;
. I wouldn't be surprised at all if it was intended behavior. I, as a user of a programming language, would expect this to work like that. Sure, that's C++, not all things are as-human-would-intuively-expect, but still.. – quetzalcoatlClang
is right, ratherGCC
is wrong. According to the first and the second quote. – xmh0511Test
is a member ofB
andA
is the enclosing namespace ofB
, where the definition ofTest
may be defined inA
, so the explicit specialization could be defined here.Test<int>
is not the name of that template and it's not the definition for templateTest
. It's a explicit specialization. henceClang
is right. – xmh0511