Я знаю, что стандарт ISO C имеет большое значение для разделения поведения перевода и поведения выполнения, частично для того, чтобы кросс-компиляторы не несли среду выполнения каждой цели.
Под этим я подразумеваю, что компилятор имеет ограниченную доступную информацию по сравнению с запущенной программой. Это ограничивает то, что вы можете сделать в исходном коде, например, не инициализировать переменную на основе возвращаемого значения из функции, подобной этой:
int twice (int val) { return val * 2; }
int xyzzy = twice (7);
int main () { printf ("%d\n", xyzzy); return 0; }
Что меня интересует, так это то, как пользовательские литералы в C ++ 11 вписываются в эту схему. Так как буквальная оценка опирается на функцию, что мешает этой функции делать такие вещи:
42_roughly
давая вам значение между 40 и 44)?Означает ли тот факт, что функция должна быть вызвана, не неужели литералы в том смысле, что их вычисляют во время компиляции?
Если это так, в чем преимущество этих литералов перед любым другим вызовом функции. Другими словами, почему это:
int xyzzy = 1101_1110_b;
предпочтительнее:
int xyzzy = makeBin ("1101_1110");
?
Секрет в том, объявляете ли вы пользовательские литеральные функции как constexpr
или нет.
Сравните это (обычная функция времени выполнения):
#include <iostream>
int operator "" _twice(unsigned long long num) { return num*2; }
int xyzzy = 7_twice;
int main () { std::cout << xyzzy << "\n"; return 0; }
С этим (константа времени компиляции, static_assert
работает):
#include <iostream>
constexpr int operator "" _twice(unsigned long long num) { return num*2; }
int xyzzy = 7_twice;
int main () {
static_assert(7_twice == 14, "not compile time constant");
std::cout << xyzzy << "\n";
return 0;
}
Очевидно, что объявление функции constexpr
ограничивает все утверждения в пределах constexpr
также, или константы времени компиляции; не допускается случайное число махинаций.
Других решений пока нет …