Hedede Hedede - 24 days ago 10
C++ Question

C++: Can std::tuple_size/tuple_element be specialized?

Is specialization of

std::tuple_size
and
std::tuple_element
permitted for custom types?
I suppose it is, but I want to be absolutely sure, and I can't find any concrete information.

Example (namespaces, member functions and
get<I>
overloads omitted):

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; };
}


I need that for use with structured bindings:

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

Answer

Specializations for user-defined types are generally fine, and always have been. N4606, [namespace.std]/1:

A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

For tuple_size, the requirements for the original template are specified in [tuple.helper]/1:

All specializations of tuple_size<T> shall meet the UnaryTypeTrait requirements with a BaseCharacteristic of integral_constant<size_t, N> for some N.

UnaryTypeTrait, in turn, in [meta.rqmts]/1:

A UnaryTypeTrait describes a property of a type. It shall be a class template that takes one template type argument and, optionally, additional arguments that help define the property being described. It shall be DefaultConstructible, CopyConstructible, and publicly and unambiguously derived, directly or indirectly, from its BaseCharacteristic, which is a specialization of the template integral_constant, with the arguments to the template integral_constant determined by the requirements for the particular property being described. The member names of the BaseCharacteristic shall not be hidden and shall be unambiguously available in the UnaryTypeTrait.

tuple_element's requirements are specified in [tuple.helper]/6 and [meta.rqmts]/3, but in the interest of brevity I won't post them here. Suffice to say that it is indeed legal to specialize...