why for-loop isn't a compile time expression and extended constexpr allows for-loop in a constexpr function

c++, c++11, c++14, constexpr

Solution

This really has nothing to do with whether or not the `constexpr` function needs to be able to be runnable at compile-time (`tuple_size<T>::value` is a constant expression regardless of whether the `T` comes from a `constexpr` object or not).

`std::get<>` is a function template, that requires an integral constant expression to be called. In this loop:

for (auto i = 0u; i < std::tuple_size<T>::value; ++i)
{
    std::get<i>(t);
}    

`i` is not an integral constant expression. It's not even constant. `i` changes throughout the loop and assumes every value from `0` to `tuple_size<T>::value`. While it kind of looks like it, this isn't calling a function with different values of `i` - this is calling different functions every time. There is no support in the language at the moment for this sort of iteration†, and this is substantively different from the original example, where we're just summing ints.

That is, in one case, we're looping over `i` and invoking `f(i)`, and in other, we're looping over `i` and invoking `f<i>()`. The second one has more preconditions on it than the first one.

†If such language support is ever added, probably in the form of a `constexpr for` statement, that support would be independent from `constexpr` functions anyway.

Problem

I wrote code like this ``` #include <iostream> using namespace std; constexpr int getsum(int to){ int s = 0; for(int i = 0; i < to; i++){ s += i; } return s; } int main() { constexpr int s = getsum(10); cout << s << endl; return 0; } ``` I understand that it works because of extended constexpr. However in this question why-isnt-a-for-loop-a-compile-time-expression, the author gave his code as follow: ``` #include <iostream> #include <tuple> #include <utility> constexpr auto multiple_return_values() { return std::make_tuple(3, 3.14, "pi"); } template <typename T> constexpr void foo(T t) { for (auto i = 0u; i < std::tuple_size<T>::value; ++i) { std::get<i>(t); } } int main() { constexpr auto ret = multiple_return_values(); foo(ret); } ``` It could not compile by GCC5.1, however, after replacing `std::get<i>(t);` with something without a specified template parameter his code did work. After reading answers under this question I found their main point is `constexpr for` creates trouble for the compiler so for-loop is used at run-time. So it makes me confused, on one hand, `for-loop` is at run-time, on the other, the loop is in a `constexpr` function, so it must be calculated at compile time, so there seems to be a contradiction. I just wonder where did I make a mistake.

Original source

Related problems