Если я хочу сделать что-то вроде перебора кортежа, мне придется прибегнуть к сумасшедшему метапрограммированию шаблонов и специализациям помощников шаблонов. Например, следующая программа не будет работать:
Код: Выделить всё
#include
#include
#include
constexpr auto multiple_return_values()
{
return std::make_tuple(3, 3.14, "pi");
}
template
constexpr void foo(T t)
{
for (auto i = 0u; i < std::tuple_size::value; ++i)
{
std::get(t);
}
}
int main()
{
constexpr auto ret = multiple_return_values();
foo(ret);
}
Потому что i не может быть константным, иначе мы не сможем его реализовать. Но циклы for — это конструкция времени компиляции, которую можно вычислять статически. Компиляторы могут удалять его, трансформировать, складывать, разворачивать или делать с ним все, что захотят, благодаря правилу «как если бы». Но тогда почему нельзя использовать циклы в духе constexpr? В этом коде нет ничего, что нужно было бы делать во время выполнения. Оптимизация компилятора является тому доказательством.
Я знаю, что потенциально вы можете изменить i внутри тела цикла, но компилятор все равно сможет обнаружить что. Пример:
Код: Выделить всё
// ...snip...
template
constexpr int foo(T t)
{
/* Dead code */
for (auto i = 0u; i < std::tuple_size::value; ++i)
{
}
return 42;
}
int main()
{
constexpr auto ret = multiple_return_values();
/* No error */
std::array arr;
}
Поскольку std::get() — это конструкция времени компиляции, в отличие от std::cout.operator
Подробнее здесь:
https://stackoverflow.com/questions/376 ... expression