C ++ 17 исправляет эту проблему для константных переменных-членов constexpr, требующих определения вне строки, если она была использована ord. См. Первоначальный ответ ниже для деталей pre C ++ 17.
Предложение P0386 Inline Variables вводит возможность применения спецификатора inline к переменным. В частности, для этого случая constexpr подразумевает inline для статических переменных-членов. В предложении говорится:
Встроенный спецификатор может применяться как к переменным, так и к функциям. Переменная, объявленная inline, имеет ту же семантику, что и функция, объявленная inline: она может быть определена идентично в нескольких единицах перевода, должна определяться в каждой единицы перевода, в которой она одурена, а поведение программы выглядит так, как будто ровно одна переменная.
и изменено [basic.def] p2:
Объявление является определением, если ...
- it объявляет статический элемент данных вне определения класса, и переменная была определена внутри класса с помощью спецификатора constexpr (это использование устарело, см. [des.static_constexpr]),
...
и добавьте [des.static_constexpr] :
Для совместимости с предыдущими стандартами C ++, статический элемент данных constexpr может быть избыточно обновляется вне класса без инициализатора. Это использование устарело. [Пример:
struct A { static constexpr int n = 5; // definition (declaration in C++ 2014) }; constexpr int A::n; // redundant declaration (definition in C++ 2014)
- конец примера]
Оригинальный ответ
В C ++ 03 нам разрешалось предоставлять только в классе intializers для const-интегралов или const перечисления типов , в C ++ 11 с использованием constexpr это было расширено до типов литералов .
В C ++ 11 нам не нужно предоставлять определение области пространства имен для статического члена constexpr, если это не odr-used , мы можем видеть это из черновика Стандартная секция C ++ 11
9.4.2
[class.static.data] , в которой говорится ( акцент мой вперед ):[ ...] Статический член данных типа literal может быть объявлен в определении класса с помощью спецификатора constexpr; если это так, в его декларации указывается логический или равный-инициализатор, в котором каждое предложение-инициализатор, являющееся выражением-присваиванием, является постоянным выражением. [Примечание. В обоих случаях член может отображаться в постоянных выражениях. -End note] Элемент все еще должен быть определен в области пространства имен, если он используется в odr (3.2) в программе, а определение области пространства имен не должно содержать инициализатор.
Итак, тогда вопрос будет, есть
baz
odr-used здесь:std::string str(baz);
, а ответ да , и поэтому нам нужна область пространства имен определение.
Итак, как мы определяем, является ли переменная odr-used ? В исходной формулировке C ++ 11 в разделе
3.2
[basic.def.odr] говорится:Выражение потенциально оценивается, если оно не является неоцененным операндом ( Пункт 5) или его подвыражение. Переменная, имя которой отображается как потенциально оцениваемое выражение, используется odr, если оно не является объектом, удовлетворяющим требованиям для появления в постоянном выражении (5.19), и немедленно применяется преобразование lvalue-to-rval (4.1).
Таким образом,
baz
дает константное выражение , но преобразование lvalue-to-rvalue не применяется сразу, поскольку оно неприменимо из-за кbaz
, являющемуся массивом. Это описано в разделе4.1
[conv.lval] , в котором говорится:Значение gl (3.10) нефункционного типа без массива T может преобразуется в prvalue.53 [...]
Что применяется в преобразовании преобразования в массив .
Это формулировка [basic.def.odr] была изменена из-за отчета о дефектах 712 , поскольку некоторые случаи не были охвачены этой формулировкой, но эти изменения не изменяют результаты для этого случая .
У меня было это сегодня на рабочем листе. Ни F9, ни включение Итеративного Вычисления не обновили соответствующие ячейки, но дважды щелкнули по ячейке и нажали Enter. Я искал справку Excel и нашел ее в статье справки под названием Изменение формулы пересчета, итерации или точности:
- Ctrl kbd> Alt kbd> F9 kbd>: dt>
- Пересчитать все формулы во всех открытых книгах, независимо от того, изменились ли они с момента последнего пересчета. Dd>
- Ctrl kbd> Shift kbd> Alt kbd> F9 kbd>: dt>
- Проверить зависимые формулы, а затем пересчитать все формулы во всех открытых книгах, независимо от того, изменились ли они с момента последнего пересчета. dd> dl>
Поэтому я попытался Ctrl kbd> Shift kbd> Alt kbd> F9 kbd> и, конечно же, все мои не пересчитываемые формулы наконец пересчитаны!
У меня была похожая проблема с VLOOKUP. Поле, которое я использовал для VLOOKUP, было отформатировано как настраиваемое поле. Excel говорил, что это число хранится в виде текста. Очистка этой ошибки (выделение всех полей с ошибкой, начало с первого с ошибкой и нажатие кнопки «Изменить на номер», даже если я не хотел, чтобы это было!) Исправили ее.
Добавьте это к вашему макросу, и он пересчитает все ячейки и формулы.
Call Application.CalculateFullRebuild
Надеюсь, это уже исправлено.
PS Приведенный выше код предназначен для людей, которые ищут макрос для решения проблемы.
Моя проблема заключалась в том, что в столбце Excel было показано "=concatenate(A1,B1)"
вместо его значения после конкатенации.
Я добавил пробел после «,» вот так =concatenate(A1, B1)
, и это сработало.
Это просто пример, который решил мою проблему.
Попробуйте и дайте мне знать, если это работает и для вас.
Иногда это работает и без пробела, но иногда это не так.
В Excel 2016 хорошо работает Alt kbd> + Ctrl kbd> + F9 kbd>.
Эта комбинация вызывает Application.CalculateFull()
функцию VBA Excel.
Это может занять много времени, если загружаются другие файлы Excel, потому что все листы Excel всех открытых книг будут вычислены снова!
Я искал функцию для вычисления конкретного листа, но не нашел что-то!