Skip to content

compile time indexing for std::array , std::tuple, std::pair, std::span #642

Description

@raidenluikang

<Описание вашей идеи>
Недавно в C++26 появился std::contant_wrapper тип, и его std::cw объекты.
Использую это класс можно добавить operator [] (std::constant_wrapper<I> ) много standard tuple-like классы, чтобы их можно использовать как обычный контайнер через оператор индексаций, и добавок получаем compile time проверка границ. Это удобно использовать чем std::get _< I > ( tuple_like) , более эргономичен чем вызов функций.

<Примеры, где ваша идея будет полезна. Чем больше примеров и чем большую аудиторию они охватывают - тем лучше>

например, если у std::tuple будет operator [] (std::constant_wrapper ]

то мы можем вызвать его так:

auto t = std::make_tuple(3, 4,  "hello world");

// old code:  auto s = std::get <2>(t);
auto s = t[std::cw <2> ];

либо можем сделать так

using point = std::pair <double, double>;
inline constexpr auto x = std::cw <0>;
inline constexpr auto y = std::cw <1>;


point p { 3.14, 2.71};
std::println("p: ( {:.3}, {:.3} ) ", p[x], p[y]);

а для std::array сразу безопасный код,

std::array<int, 4> a = {1, 2, 3, 4};
int e = a[std::cw <4>]; // compile error,  

<Код c реализацией вашей идеи, если есть>

Proposed API

For each supported type:

template<std::size_t I, class Self>
constexpr decltype(auto)
operator[](this Self&& self,
           std::constant_wrapper<I>) noexcept;

Constraints

For std::span:

requires (Extent != std::dynamic_extent)

Exposition only implementation

tuple

template<std::size_t I, class Self>
constexpr decltype(auto)
operator[](this Self&& self,
           std::constant_wrapper<I>) noexcept
{
    static_assert(
        I < std::tuple_size_v<std::remove_cvref_t<Self>>);

    return std::get<I>(std::forward<Self>(self));
}

pair

template<std::size_t I, class Self>
constexpr decltype(auto)
operator[](this Self&& self,
           std::constant_wrapper<I>) noexcept
{
    static_assert(
        I < std::tuple_size_v<std::remove_cvref_t<Self>>);

    return std::get<I>(std::forward<Self>(self));
}

array

template<std::size_t I, class Self>
constexpr decltype(auto)
operator[](this Self&& self,
           std::constant_wrapper<I>) noexcept
{
    static_assert(I < N);

    return std::forward_like<Self>(self._Elems[I]);
}

span

template<std::size_t I, class Self>
    requires (Extent != std::dynamic_extent)
constexpr decltype(auto)
operator[](this Self&& self,
           std::constant_wrapper<I>) noexcept
{
    static_assert(I < Extent);

    return std::forward<Self>(self).data()[I];
}

Полезные ссылки:

  • https://quick-bench.com/ - онлайн бенчмарк, поможет вам продемонстрировать эффективность вашего подхода
  • https://godbolt.org/ - онлайн дизассемблер
  • https://eel.is/c++draft/ - черновик стандарта C++ с возможностью ссылаться на конкретные параграфы
  • https://wg21.link/ - универсальная ссылка на международные proposal или баги в С++, например https://wg21.link/P1000 ссылается на документ P1000, а https://wg21.link/cwg100 на 100 баг в ядре языка

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions