Если я правильно понимаю ... вы выглядите следующим образом
template <auto ... as>
auto constexpr pos_nd_to_1d ()
{
std::size_t i { 0u };
((i *= DIM, i += as - 1u), ...);
return i;
}
Или, может быть, вы можете использовать std::common_type
, для i
,
std::common_type_t<decltype(as)...> i {};
, но для индексовЯ предлагаю использовать std::size_t
(также std::size_t ... as
).
Ниже приведен полный пример компиляции
#include <iostream>
constexpr auto DIM = 3u;
template <auto ... as>
auto constexpr pos_nd_to_1d ()
{
std::size_t i { 0u };
((i *= DIM, i += as - 1u), ...);
return i;
}
int main ()
{
std::cout << pos_nd_to_1d<1u, 1u, 1u>() << std::endl;
std::cout << pos_nd_to_1d<1u, 2u, 1u>() << std::endl;
std::cout << pos_nd_to_1d<1u, 3u, 1u>() << std::endl;
}
- EDIT -
ОП спрашивает
Не могли бы вы объяснить, как работает этот код? Я немного новичок в c ++.
Я лучше умею кодировать, объясняяв любом случае ...
То, что я использовал здесь
((i *= DIM, i += as - 1u), ...);
//...^^^^^^^^^^^^^^^^^^^^^^ repeated part
, называется " сложение выражения " (или также "сворачивание" или "сворачивание шаблона"), и является новой функцией C ++ 17 (вы можете получить тот же результат и в C ++ 14 (также C ++ 11, но не constexpr
), но менее простым и элегантным способом), который состоит в расширении переменнойПакет шаблонов с оператором.
Например, если вы хотите суммировать индексы, вы можете просто написать
(as + ...);
и выражение станет
(a0 + (a1 + (a2 + (/* etc */))));
Inэтот случай я использовал тот факт, чтозапятая является оператором, поэтому выражение
((i *= DIM, i += as - 1u), ...);
становится
((i *= DIM, i += a0 - 1u),
((i *= DIM, i += a1 - 1u),
((i *= DIM, i += a2 - 1u),
/* etc. */ )))))
Заметьте, что таким образом первое i *= DIM
не используется (поскольку i
инициализируется с нуля)но следующие i *= DIM
умножают as - 1u
правильное количество раз
Так, когда as...
равно 1, 2, 1
, например, вы получите
(1 - 1)*DIM*DIM + (2 - 1)*DIM + (1 - 1)