Eric Niebler 的tagged
可能会有所帮助。基本思想是您创建这样的吸气剂:
struct x_tag {
template<class Derived, class Type, std::size_t N>
struct getter {
Type& x() & {
return std::get<N>(static_cast<Derived&>(*this));
}
Type&& x() && {
return std::get<N>(static_cast<Derived&&>(*this));
}
const Type& x() const & {
return std::get<N>(static_cast<const Derived&>(*this));
}
const Type&& x() const && {
return std::get<N>(static_cast<const Derived&&>(*this));
}
};
};
您可以类似地实现y_tag
(只需将成员函数名称更改为y()
)。然后:
template<class, class, class...> struct collect;
template<class Derived, std::size_t... Ns, class... Tags>
struct collect<Derived, std::index_sequence<Ns...>, Tags...>
: Tags::template getter<Derived, std::tuple_element_t<Ns, Derived>, Ns>...{};
template<class Base, class... Tags>
struct tagged : Base, collect<tagged<Base, Tags...>,
std::index_sequence_for<Tags...>, Tags...> {
using Base::Base;
// extra polish for swap and converting from other tagged's.
};
namespace std
{
template<typename Base, typename...Tags>
struct tuple_size<tagged<Base, Tags...>>
: tuple_size<Base>
{};
template<size_t N, typename Base, typename...Tags>
struct tuple_element<N, tagged<Base, Tags...>>
: tuple_element<N, Base>
{};
}
然后
using coord_t = tagged<std::pair<int, int>, x_tag, y_tag>;