Разрешены ли пользовательские литералы во время компиляции или во время выполнения? - PullRequest
10 голосов
/ 16 апреля 2011

Интересно, потому что предопределенные литералы, такие как ULL, f и т. Д., Очевидно, разрешаются во время компиляции. Стандарт (2.14.8 [lex.ext]), похоже, не определяет это, но, похоже, стремится к времени выполнения:

[2.14.8 / 2]
Пользовательский литерал рассматривается как вызов литерального оператора или шаблона литерального оператора (13.5.8). к определить форму этого вызова для заданного пользователем литерала L с ud-суффиксом X, литерал-оператора-идентификатора чей буквенный идентификатор суффикса X ищется в контексте L с использованием правил для неквалифицированного имени поиск (3.4.1). Пусть S будет набором объявлений, найденных этим поиском. S не должно быть пустым.
(выделено мое.)

Однако мне кажется, что это приводит к ненужным накладным расходам во время выполнения, поскольку литералы могут добавляться только к значениям, которые доступны во время компиляции, например, 13.37f или "hello"_x (где _x определяется пользователем -literal).
Затем мы получили шаблонный пользовательский литерал, который никогда не будет определен в стандарте AFAICS (то есть, пример не приводится, пожалуйста, докажите, что я не прав). Эта функция каким-то волшебным образом вызывается во время компиляции или все еще во время выполнения?

Ответы [ 2 ]

7 голосов
/ 16 апреля 2011

Да, вы получаете вызов функции.Но вызовы функций могут быть скомпилированы с постоянными выражениями времени из-за constexpr буквальных операторных функций.

Например, см. this .В качестве другого примера, чтобы показать расширенную форму constexpr вычислений, разрешенных FDIS, чтобы иметь литералы времени компиляции base-26, вы можете

typedef unsigned long long ull;

constexpr ull base26(char const *s, ull ps) {
  return (*s && !(*s >= 'a' && *s <= 'z')) ? throw "bad char!" :
    (!*s ? ps : base26(s + 1, (ps * 26ULL) + (*s - 'a')));
}

constexpr ull operator "" _26(char const *s, std::size_t len) {
  return base26(s, 0);
}

Saying "bcd-"_26 вычислить выражение броска, итаким образом, возвращаемое значение становится непостоянным.В свою очередь, это приводит к тому, что любое использование "bcd-"_26 в качестве константного выражения становится неправильным, а любое непостоянное использование - кидается во время выполнения.Разрешенная форма "bcd"_26 соответствует константному выражению соответствующего вычисленного значения.

Обратите внимание, что чтение из строковых литералов явно не разрешено FDIS, однако это не представляет проблемы, и GCC поддерживает это (ссылка на символ lvalue является константным выражением, а значение символа известно во время компиляции).ИМО, если один щуриться, можно читать FDIS, как будто это разрешено делать.

Затем мы получили шаблонный пользовательский литерал, который никогда не будет определен в стандарте AFAICS (т. Е. Пример не приводится, пожалуйста, докажите, что я не прав)

Обработка литералов как вызова шаблонов литеральных операторов определена в 2.14.8.На 13.5.8 вы найдете больше примеров, подробно описывающих шаблоны функций / функций литерального оператора.

Эта функция каким-то волшебным образом вызывается во время компиляции или все еще во время выполнения?

Ключевое слово - подстановка вызова функции .Смотри 7.1.5.

0 голосов
/ 22 декабря 2012

@ Johannes S, конечно, правильно, но я бы хотел добавить (поскольку я с этим сталкивался), что даже для constexpr пользовательских литералов параметры не считаются constexpr или compileпостоянная времени, например, в том смысле, что они не могут быть использованы в качестве целочисленных констант для шаблонов.

Кроме того, только такие вещи действительно дают оценку времени компиляции:

inline constexpr long long _xx(unsigned long long v) {
  return (v > 100 ) ? throw std::exception() : v; 
}
constexpr auto a= 150_xx;

Итак, это не скомпилируется.Но это будет:

cout << 150_xx << endl;

И следующее недопустимо:

inline constexpr long long _xx(unsigned long long v) {
  return some_trait<v>::value; 
}

Это раздражает, но естественно, учитывая, что (другие) функции constexpr могут быть вызваны также во время выполнения.

Только для целочисленных пользовательских литералов можно форсировать обработку во время компиляции , используя форму шаблона.Примеры в моем вопросе и самостоятельного ответа: https://stackoverflow.com/a/13869688/1149664

...