Это невозможно. constexpr
не гарантирует встраивание значения, вы можете увидеть этот уровень оптимизации манипуляции здесь: https://godbolt.org/z/dAoiM-
Только с -O2 все встраивается и структура растворяется. Ниже этот компилятор успешно использует оценку времени выполнения даже для кода, используемого в constexpr
контексте.
Нет стандартных языковых инструментов, чтобы узнать, применяет ли компилятор определенную оптимизацию. Все сводится к как если бы правило . Если код ведет себя так же, компилятор может сделать с ним что угодно. Единственным исключением являются обязательные RVO и другие RVO (им разрешено изменять наблюдаемое поведение).
Это, как говорится. constexpr
- полезный совет. В связанном примере, если удалить спецификаторы constexpr
, даже O3
(на последних clang и gcc) не удастся удалить карту.
С точки зрения оптимизации стоит написать constexpr
функции и структуру данных, убедившись, что компилятор может оптимизировать, хотя вы не можете это заставить.
Вы можете принудительно вычислять функцию в контексте constexpr
, а также можете защищать пути не-constexpr для выброса, чтобы предотвратить гарантированную оценку во время выполнения.
#include <iostream>
#include <vector>
using namespace std;
constexpr int f(int el) {
return el > 0 ? el : throw "error";
}
int main() {
// constexpr auto r = f(-1); // #1 compiler errors that throw is forbidden in
// constexpr, so it went into a non-constexpr path
// and failed
constexpr auto r = f(1); // #2 fine - has to be interpreted in constexpr context
cout << f(1) << '\n'; // #3 fine - can be interpreted in both contexts
try {
cout << f(-1) << '\n'; // # 4 // throws - i.e. runtime evaluation
}
catch (const char* e) {
cout << e << '\n';
}
return 0;
}