Как эффективно отлаживать функции constexpr?

В C++14 получаем модернизированная версия constexpr означает, что теперь можно будет использовать циклы, if-операторы и переключатели. Рекурсия уже возможна, как в C++11.

Я понимаю, что constexpr функции / код должны быть довольно простыми, но все же возникает вопрос:как эффективно отлаживать его?

даже в "язык программирования C++, 4-е издание " есть предложение, что отладка может быть трудной.

4 ответов


есть два важных аспекта для отладки constexpr функции.

1) Убедитесь, что они используют правильный результат

здесь вы можете использовать регулярное модульное тестирование, утверждения или отладчик времени выполнения для пошагового выполнения кода. Здесь нет ничего нового по сравнению с тестированием обычных функций.

2) Убедитесь, что они могут быть оценены во время компиляции

это можно проверить, оценив функцию как правая сторона a constexpr переменной.

constexpr auto my_var = my_fun(my_arg);

для того чтобы это работало, my_fun может a) иметь только выражение константы времени компиляции в качестве фактических аргументов. Т. е. my_arg является литералом (встроенным или определяемым пользователем) или ранее вычисленным constexpr переменная или параметр шаблона, и т. д., И Б) он может только вызвать constexpr функции в его реализации (поэтому нет виртуалов, нет лямбда-выражений и т. д.).

Примечание: это очень трудно на самом деле выполнение отладки компилятора генерация кода во время компиляции оценки


ответ, который я написал 3 апреля ' 15, явно неверен. Я не могу понять, о чем я думал.

вот "реальный" ответ-метод, который я использую сейчас.

a) напишите свою функцию constexpr, как обычно. Пока это не работает.

b) когда функция вызывается во время компиляции - компиляция завершается с ошибкой не более чем сообщением о функции "invalid constexpr". Это делает его трудно понять, что проблема на самом деле есть.

C) сделать небольшую тестовую программу, которая вызывает функцию с параметрами, известными только во время выполнения. Запустите тестовую программу с помощью отладчика. Вы обнаружите, что можете отслеживать функцию обычным способом.

Мне потребовалось смущающе много времени, чтобы понять это.


Если под отладкой вы подразумеваете "сообщить, что определенное выражение не имеет желаемого значения", вы можете проверить его во время выполнения

#include <stdexcept>
#include <iostream>

constexpr int test(int x){ return x> 0 ? x : (throw std::domain_error("wtf")); }

int main()
{
  test(42);
  std::cout<< "42\n";
  test(-1);
  std::cout<< "-1\n";
}

вот мое предложение.

создать макрос:

#ifdef NDEBUG
#define OPTIONAL_CONSTEXPR constexpr
#else
#define OPTIONAL_CONSTEXPR
#endif

и заменить код типа

constexpr int x;

С

OPTIONAL_CONSTEXPR int x;

затем, если вы отлаживаете, вы сможете войти в код. Но когда вы компилируете в режиме выпуска, вы получите полное преимущество constexpr.