условие constexpr не постоянное? - PullRequest
0 голосов
/ 03 декабря 2018

Я написал следующий код C ++ 17:

constexpr bool gDebug = true;

template <typename T> constexpr const T& Select(const bool pCondition, const T& a, const T& b)
{
   if constexpr (pCondition)
   {
      return a;
   }
   else
   {
      return b;
   }
}

Затем я назвал его так:

int c = Select<QString>(gDebug, a, b); // In .cpp

Я получаю error: ‘pCondition’ is not a constant expression для строки if constexpr.

Почему?Разве это не должно работать?

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Барри прав, но я думаю, что в вашем понимании дело не в том.

template <typename T> constexpr const T& Select(const bool pCondition, const T& a, const T& b)

означает, что вызов функции может быть оценен во время компиляции, если параметры таковы.Но функцию можно вызывать с неконстантными параметрами.В этом случае сам вызов функции не является константным выражением и будет оцениваться во время выполнения.Это все еще чисто, хотя в смысле функционального программирования и, кстати, noexcept.

, но if constexpr (pCondition) {... действительно означает, что выражение должно быть вычисляемым во время компиляции.

Следовательно,Поскольку функция constexpr может вызываться с неконстантными параметрами, она не может содержать выражения, объявленные constexpr, если они зависят от этих параметров.

0 голосов
/ 03 декабря 2018

Почему?Разве это не должно работать?

Нет, не должно.pCondition не является константным выражением .Я понимаю, почему это может сбивать с толку, поскольку pCondition - это const - но термин константное выражение относится к тому, что он может быть оценен во время компиляции.То есть не const, а действительно constexpr.

Параметры функции не являются константными выражениями.Тот факт, что вы случайно передали константу времени компиляции, не имеет значения, так как вы могли бы так же легко передать переменную времени выполнения, которую вы читаете из stdin или чего-то еще.

if constexpr требует константного выражения, так что вы действительнопросто хочу if там.Или вам нужно поднять условие, чтобы оно было константным выражением, например, сделав его параметром шаблона:

template <bool pCondition, typename T>
constexpr const T& Select(const T& a, const T& b)
{
   if constexpr (pCondition) // now okay
   {
      return a;
   }
   else
   {
      return b;
   }
}

int c = Select<qDebug>(a, b);

или вы можете потребовать, чтобы параметр был значением, закодированным в тип:

template <typename Boolean, typename T>
constexpr const T& Select(Boolean pCondition, const T&, const T&);

constexpr std::true_type qDebug{}; // true_type, not bool = true
int c = Select(qDebug, a, b);      // okay
...