I know that I can partially specialize class templates, and I know that I cannot partially specify function templates.
What about variable templates? I can't find documentation on whether they can be partially specialized.
Yes, according to [temp.arg.template]/2:
Any partial specializations associated with the primary class template or primary variable template are considered when a specialization based on the template template-parameter is instantiated. ...
And to [temp.expl.spec]/7:
... the placement of partial specialization declarations of class templates, variable templates, member class templates of non-template classes, static data member templates of non-template classes, member class templates of class templates, etc. ...
It also mentioned in [constraints.namespace.std]/3:
The behavior of a C++ program is undefined if it declares an explicit or partial specialization of any standard library variable template, except where explicitly permitted by the specification of that variable template.
Not to mention that all major compilers (Clang, GCC and MSVC) have no problems with them:
template <int x, int y>
constexpr int foo = -1;
template <>
constexpr float foo<1, 0> = 1.0;
template <int x>
constexpr double foo<1, x> = 1.1;
int main()
{
static_assert(foo<0, 0> == -1, "");
static_assert(foo<0, 1> == -1, "");
static_assert(foo<1, 0> == 1.0, "");
static_assert(foo<1, 1> == 1.1, "");
}