Possible to instantiate templates using a for loop in a C++14 constexpr function?

笑着哭i 提交于 2019-12-03 23:39:32

问题


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)?


回答1:


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. A constexpr 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 as static_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 of N. As it stands, it's no different than doing this in C++11:

constexpr bool f(int x) {
    static_assert(x > 10, "..."); // invalid
    return true;
}

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:

constexpr int times_ten(int x) {
    return x * 10;
}

int main() {
   int a = times_ten(20); // notice, not constexpr
   static_assert(times_ten(20) == 200, "...");
   static_assert(a == 200, "..."); // doesn't compile
}


来源:https://stackoverflow.com/questions/20436611/possible-to-instantiate-templates-using-a-for-loop-in-a-c14-constexpr-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!