Вівторкові поради з кодування — це короткі пости про різні дрібниці, здебільшого з C++, але також і з інших мов програмування, які я використовую. Ви також можете слідкувати за хештегом #TuesdayCodingTips
на Mastodon та LinkedIn.
Функція, яка підвищує зручність у C++23, нарешті була інтегрована у Visual Studio (v17.12), після того як вона була доступна в Clang (trunk) досить довго. Ця функція — підтримка багатовимірного оператора підпису. Іншими словами, тепер ви можете перевантажити operator[]
для роботи з будь-якою кількістю аргументів.
#include
#include
#include
struct MdArray
{
auto&& operator[](this auto&& self, size_t x, size_t y)
{
if (x >= W || y >= H)
throw std::out_of_range(
std::format(
"[{}, {}] is out of bounds of [{}, {}]", x, y, W, H));
return self.data[y * W + x];
}
void print()
{
for (unsigned y = 0; y < H; y++)
{
for (unsigned x = 0; x < W; x++)
std::print("{:02} ", (*this)[x, y]);
std::println();
}
}
constexpr static size_t W = 6;
constexpr static size_t H = 3;
std::array data = { 0 };
};
int main()
{
MdArray mdArray;
mdArray[5, 2] = 42;
mdArray[1, 1] = 88;
mdArray[3, 0] = 69;
mdArray.print();
/* prints:
00 00 00 69 00 00
00 88 00 00 00 00
00 00 00 00 00 42
*/
}
Більше того, ця функція йде в парі з std::mdspan
— це невласне багатовимірне подання для 1D колекції. Цей клас досить корисний, адже зберігання 2D/3D плиткових даних у вигляді 1D масиву є дуже поширеною технікою мікрооптимізації в розробці ігор.
#include
#include
#include
int main()
{
auto&& vec = std::vector { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
// View into the data array as 3D array 2x3x2
auto&& span = std::mdspan(vec.data(), 2, 3, 2);
for (std::size_t x = 0; x < span.extent(0); ++x)
for (std::size_t y = 0; y < span.extent(1); ++y)
for (std::size_t z = 0; z < span.extent(2); ++z)
std::println("[{}, {}, {}]: {}", x, y, z, span[x, y, z]);
}
/*
[0, 0, 0]: 1
[0, 0, 1]: 2
[0, 1, 0]: 3
[0, 1, 1]: 4
[0, 2, 0]: 5
[0, 2, 1]: 6
[1, 0, 0]: 7
[1, 0, 1]: 8
[1, 1, 0]: 9
[1, 1, 1]: 10
[1, 2, 0]: 11
[1, 2, 1]: 12
*/
Цікаво, що хоча Clang підтримував цей оператор задовго до MSVC, версія trunk, як зараз встановлено в Compiler Explorer, не підтримує std::mdspan
.
Перекладено з: Tuesday Coding Tip 77 — Multidimensional subscript operator