Suppose we have the following code:
struct foo;
struct bar {
static foo mem;
template <typename> static foo tpl_mem;
};
using mem_t = decltype(bar::mem); // (1)
using tpl_mem_t = decltype(bar::tpl_mem<int>); // (2)
It is my understanding that the static specifier in both cases makes it a declaration (and not definition), thus I'm allowed to both write the code above and use those members in the decltype's unevaluated context. However, MSVC (v19.37) won't compile (2), complaining about "undefined struct foo", while perfectly compiling (1). Every other compiler I've tested this with (namely, gcc 13, clang 16, and icx 2023.2) compiles both aliases with no problem.
In the following case:
struct foo;
extern foo var;
template <typename> extern foo tpl_var;
using var_t = decltype(var);
using tpl_var_t = decltype(tpl_var<int>);
MSVC (and others) see no problem. However, if I add a specialization:
template <> extern foo tpl_var<double>; // (3)
then both MSVC and GCC complaint, but about different things. MSVC again sees "undefined struct foo", and GCC doesn't like the extern there since "explicit template specialization cannot have a storage class". Clang and icx compile it fine though.
So my questions are:
- Is the code in the first and the second blocks (without the last specialization) and my assumptions about it correct?
- Is the specialization correct (i.e., can I use
externthere?), or is GCC right about it?
UPDATE: Surprisingly enough, GCC sees no problem with extern in a partial specialization. The following works everywhere, except for MSVC:
template <typename T> extern foo tpl_var<std::vector<T>>;