Tôi đang học C++ biểu thức gấp và chúng thực sự tốt đẹp để mở rộng một gói thông số. Nhưng nếu tôi phải mở rộng một vài trong số họ trong một cuộc gọi thì sao?Sử dụng hai biểu thức gấp trong một dòng
tôi đã chuẩn bị một ví dụ để làm rõ những gì tôi có nghĩa là:
#include <cstddef>
#include <iostream>
#include <utility>
template<
template<size_t ix_, size_t iy_> typename Functor,
typename FunctorContext,
size_t... ix,
size_t... iy>
void RepeatImpl(
FunctorContext* context,
std::index_sequence<ix...>,
std::index_sequence<iy...>)
{
(Functor<ix, iy>::Execute(context), ...);
}
template<
template<size_t ix_, size_t iy_> typename Functor,
size_t width, size_t height,
typename FunctorContext>
void Repeat(FunctorContext* context)
{
RepeatImpl<Functor>(
context,
std::make_index_sequence<width>(),
std::make_index_sequence<height>());
}
template<size_t ix, size_t iy>
struct Init2dArrayFunctor
{
template<typename T>
static void Execute(T* array)
{
array[iy][ix] = 10;
}
};
int main(int, const char**)
{
constexpr size_t w = 10;
constexpr size_t h = 10;
int array[w][h] { 0 };
Repeat<Init2dArrayFunctor, w, h>(array);
for(size_t iy = 0; iy < h; ++iy)
{
for(size_t ix = 0; ix < w; ++ix)
{
std::cout << array[iy][ix] << ' ';
}
std::cout << std::endl;
}
return 0;
}
Câu hỏi của tôi là về dòng này:
(Functor<ix, iy>::Execute(context), ...);
Trong ví dụ cụ này nó sẽ mở rộng ra các cuộc gọi:
Functor<0, 0>::Execute(context)
Functor<1, 1>::Execute(context)
Functor<2, 2>::Execute(context)
...
Nhưng tôi cần nó để gọi tất cả các kết hợp của ix
và iy
gói:
Functor<0, 0>::Execute(context)
Functor<0, 1>::Execute(context)
Functor<0, 2>::Execute(context)
...
Functor<1, 0>::Execute(context)
Functor<1, 1>::Execute(context)
Functor<1, 2>::Execute(context)
...
Tôi biết rằng tôi có thể làm thêm một lớp để đi bộ qua hàng và cột (hai biểu thức lần trong các phương pháp riêng biệt sau đó):
#include <cstddef>
#include <iostream>
#include <utility>
template<
template<size_t ix_, size_t iy_> typename Functor,
size_t iRow,
typename FunctorContext,
size_t... iColumn>
void RepeatImpl_Row(
FunctorContext* context,
std::index_sequence<iColumn...>)
{
(Functor<iColumn, iRow>::Execute(context), ...);
}
template<
template<size_t ix_, size_t iy_> typename Functor,
size_t columns,
typename FunctorContext,
size_t... iRow>
void RepeatImpl(
FunctorContext* context,
std::index_sequence<iRow...>)
{
(RepeatImpl_Row<Functor, iRow>(context, std::make_index_sequence<columns>()), ...);
}
template<
template<size_t ix_, size_t iy_> typename Functor,
size_t width, size_t height,
typename FunctorContext>
void Repeat(FunctorContext* context)
{
RepeatImpl<Functor, width>(
context,
std::make_index_sequence<height>());
}
template<size_t ix, size_t iy>
struct Init2dArrayFunctor
{
template<typename T>
static void Execute(T* array)
{
array[iy][ix] = 10;
}
};
int main(int, const char**)
{
constexpr size_t w = 10;
constexpr size_t h = 10;
int array[w][h] { 0 };
Repeat<Init2dArrayFunctor, w, h>(array);
for(size_t iy = 0; iy < h; ++iy)
{
for(size_t ix = 0; ix < w; ++ix)
{
std::cout << array[iy][ix] << ' ';
}
std::cout << std::endl;
}
return 0;
}
Nhưng cách này làm cho mã khó khăn hơn nhiều để đọc. Có lẽ có thể thực hiện thủ thuật này với hai biểu thức trong một dòng?
Giải pháp này sẽ chỉ làm việc cho ví dụ tổng hợp này. Ví dụ, nó sẽ không hoạt động khi chúng ta có các kiểu variadic, không phải các chỉ mục. Tôi đã chuẩn bị ví dụ với các chỉ số vì tôi nghĩ rằng đây là cách đơn giản nhất để giải thích câu hỏi của tôi. –
@ КонстантинЛазукин nó sẽ hoạt động, chỉ cần bọc danh sách loại trong một loại chỉ mục-tuple ... –
tốt, nó là lựa chọn tốt đẹp. Nhưng có cách nào để xử lý một vài variadics qua nếp gấp? Tôi xin lỗi vì những câu hỏi khó chịu này nhưng quan điểm của tôi ở đây là tìm hiểu những gì tôi có thể thực hiện bằng tính năng C++ mới này. –