-
Notifications
You must be signed in to change notification settings - Fork 12.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The explicitly specialized primary template class shall supress consideration of other partial specialization #51051
Comments
@llvm/issue-subscribers-clang-frontend Author: None (8084cac4-606c-41d3-baea-106d693787ba)
| | |
| --- | --- |
| Bugzilla Link | [51709](https://llvm.org/bz51709) |
| Version | trunk |
| OS | All |
| CC | @DougGregor,@zygoloid |
Extended Descriptiontemplate<class T> struct A {
template<class T2> struct B {
static const int value = 1;
}; // #&#<!-- -->8203;1
template<class T2> struct B<T2*> {
static const int value = 2;
}; // #&#<!-- -->8203;2
};
template<> template<class T2> struct A<short>::B {
static const int value = 3;
}; // #&#<!-- -->8203;3
int main(){
std::cout<< A<short>::B<int*>::value; // shall be 3
} Clang give > If a member template of a class template is partially specialized, the member template partial specializations are member templates of the enclosing class template; if the enclosing class template is instantiated ([temp.inst], [temp.explicit]), a declaration for every member template partial specialization is also instantiated as part of creating the members of the class template specialization. If the primary member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template. If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template. We explicitly specialized the primary template class |
https://compiler-explorer.com/z/Ea3Gs3jzP This is... not great! |
…ates explicitly specialized for an implicitly instantiated class template specialization (#113464) Consider the following: ``` template<typename T> struct A { template<typename U> struct B { static constexpr int x = 0; // #1 }; template<typename U> struct B<U*> { static constexpr int x = 1; // #2 }; }; template<> template<typename U> struct A<long>::B { static constexpr int x = 2; // #3 }; static_assert(A<short>::B<int>::y == 0); // uses #1 static_assert(A<short>::B<int*>::y == 1); // uses #2 static_assert(A<long>::B<int>::y == 2); // uses #3 static_assert(A<long>::B<int*>::y == 2); // uses #3 ``` According to [temp.spec.partial.member] p2: > If the primary member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template. If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template. The example above fails to compile because we currently don't implement [temp.spec.partial.member] p2. This patch implements the wording, fixing #51051.
…ates explicitly specialized for an implicitly instantiated class template specialization (llvm#113464) Consider the following: ``` template<typename T> struct A { template<typename U> struct B { static constexpr int x = 0; // llvm#1 }; template<typename U> struct B<U*> { static constexpr int x = 1; // llvm#2 }; }; template<> template<typename U> struct A<long>::B { static constexpr int x = 2; // llvm#3 }; static_assert(A<short>::B<int>::y == 0); // uses llvm#1 static_assert(A<short>::B<int*>::y == 1); // uses llvm#2 static_assert(A<long>::B<int>::y == 2); // uses llvm#3 static_assert(A<long>::B<int*>::y == 2); // uses llvm#3 ``` According to [temp.spec.partial.member] p2: > If the primary member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template. If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template. The example above fails to compile because we currently don't implement [temp.spec.partial.member] p2. This patch implements the wording, fixing llvm#51051.
Extended Description
Clang give
2
, as per [temp.spec.partial.member] p2.We explicitly specialized the primary template class
B
for enclosing class template specializationA<short>
, hence the other partial specialization shall not be considered anymore.The text was updated successfully, but these errors were encountered: