С++: Может ли std:: tuple_size/tuple_element быть специализированным?

Разрешена ли специализация std::tuple_size и std::tuple_element для пользовательских типов? Я полагаю, что это так, но я хочу быть абсолютно уверенным, и я не могу найти никакой конкретной информации.

Пример (пространства имен, функции-члены и get<I> перегрузки опущены):

template <typename T, size_t N>
struct vector { T _data[N]; };

template<size_t I, typename T, size_t N>
constexpr T& get(vector<T,N>& vec) { return vec._data[I]; }

namespace std {
template<typename T, size_t N>
class tuple_size< vector<T,N> > : public std::integral_constant<size_t, N> { };
template<size_t I, typename T, size_t N>
class tuple_element< I, vector<T,N> > { public: using type = T; };
}

Мне нужно это для использования со структурированными привязками:

void f(vector<T,3> const& vec)
{
    auto& [x,y,z] = vec;
    // stuff...
}

Ответ 1

Специализации для пользовательских типов, как правило, прекрасны и всегда были. N4606, [namespace.std]/1:

Программа может добавлять специализацию шаблона для любого стандартного шаблона библиотеки в пространство имен std только в том случае, если объявление зависит от пользовательского типа, а специализация соответствует требованиям стандартной библиотеки для исходного шаблона и явно не запрещена.

Для tuple_size требования к исходному шаблону указаны в [tuple.helper]/1:

Все специализации tuple_size<T> должны соответствовать требованиям UnaryTypeTrait с BaseCharacteristic of integral_constant<size_t, N> для некоторого N.

UnaryTypeTrait, в свою очередь, в [meta.rqmts]/1:

В UnaryTypeTrait описывается свойство типа. Он должен быть шаблоном класса, который принимает один аргумент типа шаблона и, необязательно, дополнительные аргументы, которые помогают определить описываемое свойство. Он должен быть DefaultConstructible, CopyConstructible и публично и однозначно выводиться прямо или косвенно из его BaseCharacteristic, который является специализацией шаблона integral_constant, с аргументами к шаблону integral_constant, определяемым требованиями для описываемое конкретное свойство. Имена членов BaseCharacteristic не должны быть скрыты и должны быть однозначно доступны в UnaryTypeTrait.

Требования

tuple_element указаны в [tuple.helper]/6 и [meta.rqmts]/3, но в интересах краткости я не буду публиковать их здесь. Достаточно сказать, что действительно законно специализироваться...