Почему бы * * не * * объявить функцию 'constexpr'?


любая функция, состоящая только из оператора return, может быть объявлена constexpr и таким образом позволит быть вычислено во время компиляции, если все аргументы - это constexpr и только constexpr функции вызываются в тело. есть ли причина не объявлять любой такая функция constexpr ?

пример:

  constexpr int sum(int x, int y) { return x + y; }
  constexpr i = 10;
  static_assert(sum(i, 13) == 23, "sum correct");

может ли кто-нибудь привести пример, где объявление функции constexpr будет делать каких-либо вред?


некоторые начальные мысли:

даже если не должно быть никаких веских причин для объявления функции не constexpr Я мог себе представить, что constexpr ключевого слова переходная роль: ее отсутствие в коде, который не требует времени компиляции оценки позволят компиляторам, которые не реализуют время компиляции оценки по-прежнему для компиляции этого кода (но для надежного сбоя в коде это нуждается в них, как сделано явным с помощью constexpr).

но чего я не понимаю: если не должно быть веской причины для когда-либо объявляя функцию не constexpr, почему

3 55

3 ответа:

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

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

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

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

Я думаю, что вы имеете в виду называется частичное оценке. Вы касаетесь того, что некоторые программы могут быть разделены на две части - часть, которая требует информации о времени выполнения, и часть, которая может быть выполнена без какой - либо информации о времени выполнения, и что теоретически вы можете просто полностью оценить часть программы, которая не нуждается в какой-либо информации о времени выполнения, Прежде чем вы даже начнете запускать программу. Есть некоторые языки программирования, которые делают это. Например, язык программирования D имеет встроенный в компилятор интерпретатор, который позволяет выполнять код во время компиляции при условии, что он соответствует определенным ограничениям.

есть несколько основных проблем в получении частичной оценки работы. Во-первых, это значительно усложняет логику компилятора, потому что компилятор должен будет иметь возможность имитировать все операции, которые вы могли бы поместить в исполняемую программу во время компиляции. Это, в худшем случае, необходимо имейте полный интерпретатор внутри компилятора, что делает сложную проблему (написание хорошего компилятора C++) и делает ее на порядок сложнее.

Я считаю, что причина текущей спецификации о constexpr просто ограничить сложность компиляторов. Случаи, которыми он ограничен, довольно просты для проверки. Нет необходимости реализовывать циклы в компиляторе (что может вызвать целый ряд других проблем, например, что произойдет, если вы получите бесконечный цикл внутри компилятора). Это также позволяет избежать компилятору потенциально оценивать операторы, которые могут вызвать segfaults во время выполнения, например, после плохого указателя.

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

обобщить, нет никакой теоретической причины, по которой вы не могли бы частично оценить программы на C++ во время компиляции. На самом деле, люди делают это все время. Оптимизирующие компиляторы, например, по существу являются программами, которые пытаются сделать это как можно больше. Метапрограммирование шаблонов-это один из примеров, когда программисты на C++ пытаются выполнить код внутри компилятора, и с шаблонами можно сделать некоторые большие вещи частично потому, что правила для шаблонов образуют функциональный язык, который компилятор имеет более простой время реализации. Кроме того, если вы думаете о компромиссе между часами автора компилятора и часами программирования, метапрограммирование шаблонов показывает, что если вы в порядке, заставляя программистов наклоняться назад, чтобы получить то, что они хотят, вы можете построить довольно слабый язык (система шаблонов) и сохранить сложность языка простой. (Я говорю " слабый "как" не особенно выразительный", а не" слабый " в смысле теории вычислимости).

надеюсь, что это помогает!

Если функция имеет побочные эффекты, вы не хотите, чтобы пометить его constexpr. пример

Я не могу получить никаких неожиданных результатов от этого, на самом деле это выглядит как gcc 4.5.1 просто игнорирует constexpr