Кому интересно — там вообще довольно забавная история. Иметь VLA в какой-то форме (т.е. по сути — типобезопасный и стандартизированный alloca) всем хочется, но представления о том, как он должен выглядеть, были разные. Одна группа проталкивала уже существующий в C99 вариант, с основной мотивацией в виде совместимости с C, но он изрядно усложняет язык, поэтому их выпилили.
С другой стороны был вариант с std::dynarray, который определен как библиотечный класс, но с таким интерфейсом, чтобы компилятор по факту мог сделать хитрооптимизированную реализацию с выделением на стеке (а мог и не делать — т.е. это QoI, а не требование). Его тоже сначала сгоряча добавили в C++14 (самое забавное, что в стандарте некоторое время были обе эти вещи), а потом выпилили на более поздних этапах, но не окончательно, а с выносом в отдельный Arrays TS. Так что в C++17 он, видимо, будет именно в таком виде.
В каком именно новом стандарте? Я цитировал C++14, это актуальная на данный момент версия стандарта. То, что вы привели — это из текущего черновика C++17?
Очень жаль, что вас за это минусуют зачем-то. Это, мягко говоря, неочевидная вещь, про которую в книгах обычно не прочитаешь, компиляторы могут расширять стандарт (и более того, если они и так реализуют C99, то им легче здесь допустить расширение, чтобы не держать разную логику для C и C++), а сам стандарт C++14 — книга на 1300 страниц, которую читают, в основном, авторы компиляторов и библиотек в Boost, ну и language lawyers :)
Такого параграфа нет, поскольку C++ отпочковался от C до появления стандарта C99 (в 98-м году). Поэтому в соответствующем разделе стандарта (C.1[diff.iso]) описывается разница с C89.
Впрочем, это не суть важно — стандарт плюсов вообще практически ничего не определяет в терминах «а вот это как в C», за исключением стандартной библиотеки, и весь раздел C в нем носит не нормативный, а информативный характер. Поэтому конкретно вопрос с объявлением массивов решается чтением соответствующего параграфа стандарта, а именно 8.3.4[dcl.array], в котором в первой же строчке дан синтаксис соответствующего декларатора:
In a declaration T D where D has the form
D1 [ constant-expressionopt] attribute-specifier-seqopt
И там же дальше:
If the constant-expression (5.19) is present, it shall be a converted constant expression of type std::size_t and its value shall be greater than zero.
Тут речь, вообще-то, о плюсах, в которых нет VLA. То, что gcc компилирует ваш код — это следствие того, что он поддерживает сишные VLA в плюсах как языковое расширение, но по стандарту это ошибка. Кстати, со времен C99 появился еще C11, в котором эта фича сделана conditionally supported, т.е. не все компиляторы обязаны ее поддерживать.
Впрочем, в моем оригинальном примере подразумевалось, что этот код не в функции. В этом случае константа таки требуется даже и в С99, VLA там допустим только для локальных переменных.
Тут надо отметить, что даже если переменная ODR-used, это не налагает на компилятор обязательство выделять память. В конечном счете, если подобное выделение не наблюдаемо в самой программе, то включается правило «as if».
Понятие integral constant expression в стандарте было с самого начала, и статический (явно или неявно) const int с соответствующим инициализатором под него тоже всегда подпадал. Но это все перпендикулярно тому, выделяется ли память под переменную. Т.е. если у вас написано что-то вот такое:
const int n = 0;
int a[n];
То компилятор обязан это съесть, хотя размер массива обязан быть константой времени компиляции. Но при этом он имеет полное право выделить память под n как переменную.
>> раньше описав такую константу в классе в .h её приходилось описывать ещё и в .cc файле даже если её адрес никогда явно не брался.
Для констант, у которых инициализатором является integral constant expression, их всегда можно было определять в теле класса вместе с инициализатором, а определять их снаружи требовалось только тогда, когда берется их адрес.
Потому что IL по степени высокоуровневости примерно как тот же C (а местами и куда повыше). Там надо смотреть, что потом сгенерит JIT из этого байткода.
Я не веб-программист, поэтому мне тяжело сказать конкретно насчет XMLHttpRequest. Но в гуевых приложениях чрезмерное использование синхронных API и игнор асинхронных исторически являются огромной проблемой, из-за которой вы видите пресловутый «бублик» ожидания куда чаще, чем надо. В WinRT, кстати, именно из-за этого практически все API сделали асинхронными без синхронных вариантов, по принципу «не умеешь — научим, не хочешь — заставим».
Асинхронность сама по себе ортогональна последовательному выполнению, кстати. В этом смысле промисы не «сихрноннее» обычных коллбэков. Просто с ними проще делать композицию — не обязательно последовательную.
Насчет кривости кода — это во многом фактор языка. В C# писать асинхронный код стало буквально в разы проще с появлением async/await, который позволяет размотать лапшу из continuation-лямбд в нормальный код, который выглядит абсолютно как синхронный, за исключением этого самого await в точках передачи управления. В ES6 подобное тоже планируется.
Это уже от реализации JS в браузере зависит, нет? В принципе нет никаких причин, по которым JS должен крутиться на том же потоке, что и рендеринг, и обработка ввода.
Основная причина — синхронные запросы, если их сделать, будут использоваться не только в таких случаях, но и в других, где на самом деле нужна асинхронность, просто потому, что их проще использовать (а быдлокодеров, которые кодят по шаблонам по принципу «что короче и понятнее», куда больше, чем тех, кто будет разбираться).
А в GUI-приложении, таких случаев на самом деле куда больше, чем тех, где синхронность пойдет. Поэтому, если оставшиеся в меньшинстве случаи можно адекватно покрыть асинхронностью, даже за счет небольшого усложнения кода, то лучше оставить только асинхронные API.
Ну и в вашем конкретном примере, все же может потребоваться выполнять какой-то JS, когда остальное грузится. Анимированный индикатор прогресса, положим, вы сделаете на CSS, а вот какие-нибудь хитрые таймауты — уже нет.
>> Да и вообще, наличие инструмента лучше, чем его отстутствие.
Далеко не всегда. Если инструмент в 90% случаев будут использовать некорректно (т.е. писать синхронный код там, где на самом деле нужен асинхронный, просто потому, что так проще, или потому, что автор увидел синхронный метод первым), то его может быть лучше убрать. Или, по крайней мере, спрятать подальше.
У фильтров, кстати, есть очень забавный побочный эффект — поскольку они выполняются до отмотки кода, то они предоставляют потенциальную точку для выполнения внешнего (по отношению к вашему классу) кода, который может наблюдать состояние объекта. Все вроде бы ничего, но если у вас в методе есть код, который временно нарушает инварианты класса, то фильтры могут увидеть этот нарушенный инвариант.
Например, в классе есть два связанных друг с другом поля. Код обновляет сначала одно, а потом второе, при этом вычисление нового значения для поля может кинуть исключение. Обычно подобное оборачивают в try/finally, где в finally возвращают объект в изначальное состояние. Но фильтры выполняются до finally, и если у них есть ссылка на ваш объект, они могут увидеть его в состоянии, где первое поле уже обновилось, а второе — еще нет, и связывающий их инвариант нарушен.
Конкретно $(BlaBlaBla) — на практике это сущность MSBuild, да, и разворачивает их он (если попросят).
Под капотом там создается экземпляр класса Project, а на нем дергается метод GetEvaluatedProperty, который и возвращает развернутое значение. При записи, соответственно, зовется SetProperty. Для редактирования же значение проперти обычно читается в исходном виде непосредственно из коллекции Properties, чтобы отобразить его точно в том виде, в котором оно было в файле проекта, со всеми $(...).
Про Macros я просто пропустил. Это (точнее — project macros) терминология, специфичная для C++-проектов, больше её никто не использует. Если мне не изменяет память, она осталась с тех времен, когда C++-проекты были не MSBuild. По факту на сегодня она просто отдается на откуп мсбилду, но в документации, тем не менее, она зачем-то описана как отдельная сущность.
(гипотетически, если MSBuild завтра внезапно умрет, то макросы его переживут, поэтому какой-то смысл в том, чтобы говорить о них в отдельности, наверное есть)
Можно, понятие редактора не привязано к проектной системе — ассоциация идет обычно по типу файла (т.е. расширению). Проектная система может перехватить открытие файла и насильно заставить открыть какой-то редактор по умолчанию для данного типа, отличный от глобального умолчания (например, PTVS перехватывает открытие .html в Django-проектах, чтобы открыть их в своем редакторе, который понимает синтаксис Django). Но в любом случае остается вариант в виде Open With в контекстном меню файла — там будут вообще все зарегистрированные в VS редакторы, и можно выбрать любой. Вполне вероятно, что ваш редактор где-то там :)
(Кому интересно, покопайтесь здесь и здесь)
Кому интересно — там вообще довольно забавная история. Иметь VLA в какой-то форме (т.е. по сути — типобезопасный и стандартизированный alloca) всем хочется, но представления о том, как он должен выглядеть, были разные. Одна группа проталкивала уже существующий в C99 вариант, с основной мотивацией в виде совместимости с C, но он изрядно усложняет язык, поэтому их выпилили.
С другой стороны был вариант с std::dynarray, который определен как библиотечный класс, но с таким интерфейсом, чтобы компилятор по факту мог сделать хитрооптимизированную реализацию с выделением на стеке (а мог и не делать — т.е. это QoI, а не требование). Его тоже сначала сгоряча добавили в C++14 (самое забавное, что в стандарте некоторое время были обе эти вещи), а потом выпилили на более поздних этапах, но не окончательно, а с выносом в отдельный Arrays TS. Так что в C++17 он, видимо, будет именно в таком виде.
Впрочем, это не суть важно — стандарт плюсов вообще практически ничего не определяет в терминах «а вот это как в C», за исключением стандартной библиотеки, и весь раздел C в нем носит не нормативный, а информативный характер. Поэтому конкретно вопрос с объявлением массивов решается чтением соответствующего параграфа стандарта, а именно 8.3.4[dcl.array], в котором в первой же строчке дан синтаксис соответствующего декларатора:
И там же дальше:
Впрочем, в моем оригинальном примере подразумевалось, что этот код не в функции. В этом случае константа таки требуется даже и в С99, VLA там допустим только для локальных переменных.
То компилятор обязан это съесть, хотя размер массива обязан быть константой времени компиляции. Но при этом он имеет полное право выделить память под n как переменную.
>> раньше описав такую константу в классе в .h её приходилось описывать ещё и в .cc файле даже если её адрес никогда явно не брался.
Для констант, у которых инициализатором является integral constant expression, их всегда можно было определять в теле класса вместе с инициализатором, а определять их снаружи требовалось только тогда, когда берется их адрес.
Асинхронность сама по себе ортогональна последовательному выполнению, кстати. В этом смысле промисы не «сихрноннее» обычных коллбэков. Просто с ними проще делать композицию — не обязательно последовательную.
Насчет кривости кода — это во многом фактор языка. В C# писать асинхронный код стало буквально в разы проще с появлением async/await, который позволяет размотать лапшу из continuation-лямбд в нормальный код, который выглядит абсолютно как синхронный, за исключением этого самого await в точках передачи управления. В ES6 подобное тоже планируется.
А в GUI-приложении, таких случаев на самом деле куда больше, чем тех, где синхронность пойдет. Поэтому, если оставшиеся в меньшинстве случаи можно адекватно покрыть асинхронностью, даже за счет небольшого усложнения кода, то лучше оставить только асинхронные API.
Ну и в вашем конкретном примере, все же может потребоваться выполнять какой-то JS, когда остальное грузится. Анимированный индикатор прогресса, положим, вы сделаете на CSS, а вот какие-нибудь хитрые таймауты — уже нет.
Это как раз кейс для промисов — строите из них нужную цепочку, вот вам и последовательность.
Далеко не всегда. Если инструмент в 90% случаев будут использовать некорректно (т.е. писать синхронный код там, где на самом деле нужен асинхронный, просто потому, что так проще, или потому, что автор увидел синхронный метод первым), то его может быть лучше убрать. Или, по крайней мере, спрятать подальше.
Например, в классе есть два связанных друг с другом поля. Код обновляет сначала одно, а потом второе, при этом вычисление нового значения для поля может кинуть исключение. Обычно подобное оборачивают в try/finally, где в finally возвращают объект в изначальное состояние. Но фильтры выполняются до finally, и если у них есть ссылка на ваш объект, они могут увидеть его в состоянии, где первое поле уже обновилось, а второе — еще нет, и связывающий их инвариант нарушен.
Под капотом там создается экземпляр класса Project, а на нем дергается метод GetEvaluatedProperty, который и возвращает развернутое значение. При записи, соответственно, зовется SetProperty. Для редактирования же значение проперти обычно читается в исходном виде непосредственно из коллекции Properties, чтобы отобразить его точно в том виде, в котором оно было в файле проекта, со всеми $(...).
Про Macros я просто пропустил. Это (точнее — project macros) терминология, специфичная для C++-проектов, больше её никто не использует. Если мне не изменяет память, она осталась с тех времен, когда C++-проекты были не MSBuild. По факту на сегодня она просто отдается на откуп мсбилду, но в документации, тем не менее, она зачем-то описана как отдельная сущность.
(гипотетически, если MSBuild завтра внезапно умрет, то макросы его переживут, поэтому какой-то смысл в том, чтобы говорить о них в отдельности, наверное есть)