I've been messing around with an SVN build of clang to experiment with the relaxed rules for constexpr
. One of the things I've been unable to determine as of yet is whether it's possible to loop through the elements inside a tuple at compile-time in a constexpr function.
Because I don't have a C++14 compliant standard library to test on, I've prepared the following equivalent test:
template<int N>
constexpr int foo() {
return N;
}
constexpr int getSum() {
auto sum = 0;
for (auto i = 0; i < 10; ++i) {
sum += foo<i>();
}
return sum;
}
constexpr auto sum = getSum();
The interesting part here is foo<i>()
. In a non-constexpr function I would expect this to fail to compile, because you simply cannot use a runtime int to generate a compile-time instantiation of a template. Because this is a constexpr
function, however, I question whether this would be possible. In particular, the value is known at compile-time, even if it is allowed to mutate.
I know that the following code will compile:
constexpr auto nValue = 2;
foo<nValue>();
In SVN clang, my first example does not:
test2.cpp:19:12: error: no matching function for call to 'foo' sum += foo(); ^~~~~~ test2.cpp:11:15: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'N' constexpr int foo() { ^
For starters, I struggle to interpret the second part of this error message. That aside, is it mandated by the C++14 standard, and if so, does anyone know why this syntax wouldn't be allowed (simple oversight or to protect against something)?
That's because
constexpr
is not exclusive to compile-time computations or usage. Aconstexpr
function is just that, allowing a function (or variable) to be used in a constant expression. Outside of that, they're regular functions. A constant expression just so happens to be required in certain contexts such asstatic_assert
or array sizes, etc that are compile-time only situations.You'll notice in your code that you loop through a variable but the variable you're looping through itself isn't
constexpr
so it isn't a constant expression to be used in that template instantiation ofN
. As it stands, it's no different than doing this in C++11:Which is obviously invalid because as I mentioned earlier, you don't have to use
constexpr
functions in exclusive compile-time situations. For example, nothing is stopping you from doing this: