Does anyone know if this explicit specialization is or is not valid:
template <class>
struct L {
template <typename T>
struct O {
template <typename U>
static void Fun(U);
};
};
template<>
template<typename T>
template<typename U>
void L<int>::O<T>::Fun(U) {}
clang trunk (12/3/2013) gives the following error:
f:...\test.cpp:36:20: error: out-of-line definition of 'Fun' from class 'O' without definition
void L<int>::O<T>::Fun(U) {}
~~~~~~~~~~~~~~^
1 error generated.
Any supporting references from the standard to justify your answer will be greatly appreciated!
Note: I am somewhat surprised that it is an error - I would expect the specialization to be picked for any family of template arguments with which 'Fun' is instantiated beginning with <int><?any><?any>.
Is this a clang bug or a bug in my expectations?
Thank you!
====== EDIT (I think I have an answer) ========
OK - i think i found the supporting wording - from N3797 (post-chicago 2013 working draft) - 14.7.3/16 =>
"In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well."
If i interpret this correctly, we need an explicit specialization of O if we're going to declare an explicit specialization of its member? Hence the error.
Correct?
Thanks!
I don't believe it is valid. I'm not deep enough in the language to tell you how/if you can do this without providing the top-level specialization as done below, or if there is a shortcut for skipping the replicate templates, but the error message is fairly clear: You're trying to provide an implementation of a static member of a dependent nested type without providing the specialization of the actual dependency. I.e. this works:
#include <iostream>
template <typename>
struct L
{
template <typename T>
struct O
{
template <typename U>
static void Fun(U)
{
std::cout << "General: " << __PRETTY_FUNCTION__ << std::endl;
};
};
};
// provide specialized L
template<>
struct L<int>
{
template <typename T>
struct O
{
template <typename U>
static void Fun(U);
};
};
// L<int> is a specialized type, so provide the rest.
template<typename T>
template<typename U>
void L<int>::O<T>::Fun(U)
{
std::cout << "Special: " << __PRETTY_FUNCTION__ << std::endl;
}
int main()
{
L<int>::O<double> nobj;
nobj.Fun(10);
L<double>::O<int> nobj2;
nobj2.Fun(20);
return 0;
}
Output
Special: static void L<int>::O<double>::Fun(U) [T = double, U = int]
General: static void L<double>::O<int>::Fun(U) [T = int, U = int]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With