Возможно ли создавать шаблоны с использованием цикла for в функции constexpr С++ 14?
Я возился с SVN-сборкой clang, чтобы экспериментировать с непринужденными правилами для constexpr
. Одной из вещей, которые мне пока не удалось определить, является возможность циклического прохождения элементов внутри кортежа во время компиляции в функции constexpr.
Поскольку у меня нет стандартной библиотеки, совместимой с С++ 14 для тестирования, я подготовил следующий эквивалентный тест:
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();
Интересная часть здесь foo<i>()
. В функции, отличной от constexpr, я ожидал бы, что это не скомпилируется, потому что вы просто не можете использовать runtime int для создания экземпляра шаблона во время компиляции. Однако, поскольку это функция constexpr
, я задаюсь вопросом, возможно ли это. В частности, значение известно во время компиляции, даже если ему разрешено мутировать.
Я знаю, что следующий код будет скомпилирован:
constexpr auto nValue = 2;
foo<nValue>();
В SVN clang мой первый пример не делает:
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() {
^
Во-первых, я пытаюсь интерпретировать вторую часть этого сообщения об ошибке. В стороне, это предусмотрено стандартом С++ 14, и если да, то кто-нибудь знает, почему этот синтаксис не будет разрешен (простой надзор или защита от чего-то)?
Ответы
Ответ 1
В стороне, это предусмотрено стандартом С++ 14, и если да, то кто-нибудь знает, почему этот синтаксис не будет разрешен (простой контроль или защита от чего-то)?
Это потому, что constexpr
не является эксклюзивным для вычислений или использования времени. Функция constexpr
- это просто то, что позволяет использовать функцию (или переменную) в постоянном выражении. Кроме того, они являются регулярными функциями. Постоянное выражение просто так требуется в определенных контекстах, таких как static_assert
или размеры массива и т.д., Которые являются только ситуациями времени компиляции.
В коде вы заметите, что вы перебираете переменную, но переменная, которую вы зацикливаете сама по себе, не является constexpr
, поэтому в этом экземпляре шаблона N
не используется константное выражение, Как бы то ни было, это не отличается от этого в С++ 11:
constexpr bool f(int x) {
static_assert(x > 10, "..."); // invalid
return true;
}
Что явно недействительно, поскольку, как я упоминал ранее, вам не нужно использовать функции constexpr
в исключительных ситуациях компиляции. Например, ничто не мешает вам сделать это:
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
}