The rules for legal placement of explicit specializations as per [temp.expl.spec] are not entirely easy to grasp, particularly when mixing with hidden friends, so as to avoid the immolation[temp.expl.spec]/8 of my specializations and friend functions I wish a second opinion(1) on the following:
(1) My own interpretation of the standard says that the answer is "yes; this is legal", as per the standard references below.
Or, with an example: is the following program well-formed?
// s.h
#pragma once
template <int N>
struct S {
struct M;
};
template<>
struct S<42>::M {
friend int f(M) { return 42; }
};
// foo.h
#pragma once
void foo();
// foo.cpp
#include "foo.h"
#include <iostream>
#include "s.h"
void foo() {
std::cout << f(S<42>::M{});
}
// main.cpp
#include <iostream>
#include "foo.h"
#include "s.h"
int main() {
std::cout << f(S<42>::M{});
foo();
}
Note that friends defined at their friend declarations are inline as per [class.friend]/7, so whilst I'm somewhat worried about ODR-violations it is not for the friend but rather for the member class specialization. I think [basic.def.odr]/6 applies here if we consider S<42>::M
as "just" a class type.
Clang and GCC both accepts the above, but this may not be significant in case the program is ill-formed NDR or has undefined behaviour. GCC 10.1.0 DEMO, Clang 10.0.0 DEMO.
Yes, an explicit specialization of a templated class (which includes class templates and member classes of class templates) is a class, and so multiple definitions are allowed under the usual circumstances. Those definitions are treated as if there were but one in the program, so f
is OK as well. (It’s not clear that implicit inline
does anything here, since there is only one definition of f
to the extent that there is only one of S<42>::M
as a whole.) Neither does the lack of definition for S<N>::M
mean anything here; a “member explicit specialization” like this is really an abbreviated specialization of the enclosing class template S
, so S<42>::M
is quite unrelated.
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