Constexpr static std::array<const char *,5> не удалось скомпилировать с MSVC2013

У меня есть этот код:

#include <array>
#include <iostream>

class ExternalGeometryExtension
{
public:
    enum Flag {
        Defining = 0,
        Frozen = 1, 
        Detached = 2,
        Missing = 3,
        Sync = 4,
        NumFlags
    };

    constexpr static std::array<const char *,NumFlags> flag2str{{ "Defining", "Frozen", "Detached","Missing", "Sync" }};
};

int main()
{
    std::cout << ExternalGeometryExtension::flag2str[ExternalGeometryExtension::Frozen] << std::endl;
    return 0;
}

Он отлично компилируется с: clang версии 5.0.0 и gcc (Убунту 4.8.4-2Убунту1~14.04.3) 4.8.4

Не удается скомпилировать с MSVC2013.

Ошибка компиляции:

 C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2144: syntax error : 'int' should be preceded by ';' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2146: syntax error : missing ';' before identifier 'flag2str' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2838: 'array<char const *,5>' : illegal qualified name in member declaration [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2143: syntax error : missing ';' before '{' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2334: unexpected token(s) preceding '{'; skipping apparent function body [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod\Sketcher\App\ExternalGeometryExtension.cpp(36): error C2143: syntax error : missing ';' before 'std::array<const char *,0x05>' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod\Sketcher\App\ExternalGeometryExtension.cpp(36): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod\Sketcher\App\ExternalGeometryExtension.cpp(36): error C2039: 'flag2str' : is not a member of 'Sketcher::ExternalGeometryExtension' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         c:\projects\freecad\src\mod\sketcher\app\ExternalGeometryExtension.h(47): error C2144: syntax error : 'int' should be preceded by ';' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         c:\projects\freecad\src\mod\sketcher\app\ExternalGeometryExtension.h(47): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         c:\projects\freecad\src\mod\sketcher\app\ExternalGeometryExtension.h(47): error C2146: syntax error : missing ';' before identifier 'flag2str' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         c:\projects\freecad\src\mod\sketcher\app\ExternalGeometryExtension.h(47): error C2838: 'array<char const *,5>' : illegal qualified name in member declaration [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         c:\projects\freecad\src\mod\sketcher\app\ExternalGeometryExtension.h(47): error C2143: syntax error : missing ';' before '{' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         c:\projects\freecad\src\mod\sketcher\app\ExternalGeometryExtension.h(47): error C2334: unexpected token(s) preceding '{'; skipping apparent function body [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2144: syntax error : 'int' should be preceded by ';' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2146: syntax error : missing ';' before identifier 'flag2str' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2838: 'array<char const *,5>' : illegal qualified name in member declaration [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2143: syntax error : missing ';' before '{' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod/Sketcher/App/ExternalGeometryExtension.h(47): error C2334: unexpected token(s) preceding '{'; skipping apparent function body [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]
         C:\projects\freecad\src\Mod\Sketcher\App\ExternalGeometryExtensionPyImp.cpp(67): error C2039: 'flag2str' : is not a member of 'Sketcher::ExternalGeometryExtension' [C:\projects\freecad\build\src\Mod\Sketcher\App\Sketcher.vcxproj]

Полный вывод компилятора здесь

Мои вопросы: Что я делаю неправильно? Почему не компилируется с MSVC2013?

Могу ли я что-то сделать, чтобы этот код работал с MSVC2013, не нарушая его в других компиляторах?

Обновлено: я изменил код, чтобы он был минимальным, полным и проверяемым примером, как запросил Тоби Спейт, основываясь на правильном предположении Диодака. Я не могу вывести ошибку этого конкретного кода, потому что у меня нет копии MSVC2003. Я работаю над FreeCAD с открытым исходным кодом, который предлагает поддержку Windows. Я использую линукс. В любом случае ошибки в выводе соответствуют коду, который я показываю. Это результат теста AppVeyor перед интеграцией. Код отлично проходит Linux CI. Я постараюсь максимально использовать этот вопрос, надеясь, что он будет полезен для других.

Обновлено еще раз: я понял, что инициализация двойной скобки вызвала некоторые удивления. Из примера в cppreference:

double-braces required in C++11 prior to the CWG 1270 revision (not needed in C++11 after the revision and in C++14 and beyond)

Без двойных скобок gcc 4.8 не работает.

MSVC2013 устарел. И его поддержка С++ 11 была неполной. До недавнего времени у MS действительно не было приличного компилятора для C++11.

StoryTeller - Unslander Monica 03.04.2019 13:55

Как ежедневный пользователь VS2013, я знаю только два варианта: запретить «новые» стильные функции C++ или #ifdef альтернативный код, совместимый с VS2013. Оба варианта неудовлетворительны... ;-)

Scheff's Cat 03.04.2019 14:05

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

Toby Speight 03.04.2019 14:39

@Scheff Вы ответили на последний вопрос. Я думал об этом варианте. Как вы указываете, это неудовлетворительно. Я, вероятно, отброшу constexpr и перенесу определение за пределы класса. Спасибо вам.

Abdullah Tahiri 05.04.2019 09:32

@Toby Speight Я отредактировал вопрос, чтобы сделать полностью рабочий пример с помощью Диодака. Как я указываю сейчас в вопросе, у меня нет доступа к фактическим сообщениям об ошибках этого сокращенного примера. Спасибо за указание на это.

Abdullah Tahiri 05.04.2019 09:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
5
161
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Согласно этому блог разработчиков Майкрософт, constexpr является одной из основных функций языка С++ 11, которая не поддерживается в VS 2013. И только частично поддерживается в CTP за ноябрь 2013 г.

Да, это отвечает на мой вопрос. Код совместим с C++11, но MSVC2013 не поддерживает полный стандарт. Я не смог найти этот ответ самостоятельно. Спасибо большое.

Abdullah Tahiri 05.04.2019 09:22

Что ж, рассматриваемый код компилируется с опцией С++ 17:

#include <array>
#include <iostream>

class ExternalGeometryExtension
{
public:
    enum Flag {
        Defining = 0,
        Frozen = 1, 
        Detached = 2,
        Missing = 3,
        Sync = 4,
        NumFlags
    };

    constexpr static std::array<const char *,NumFlags> flag2str{{ "Defining", "Frozen", "Detached","Missing", "Sync" }};
};

int main()
{
    std::cout << ExternalGeometryExtension::flag2str[ExternalGeometryExtension::Frozen] << std::endl;
    return 0;
}

И нет необходимости повторно объявлять статическую переменную вне класса.

@Abdullah Tahiri Пожалуйста, используйте конструкции С++ 11 (как указано в вопросительных метках) или перейдите на С++ 17 для всех функций. Но я боюсь, что MSVC может вызвать проблемы с кодом. Есть ли какая-то особая причина, по которой вы не можете использовать GCC или CLang в Windows?

Спасибо за очистку/дополнение кода. Я использовал ваш пример в вопросе, чтобы он был понятен в будущем. Я думаю, что все мои конструкции соответствуют стандарту С++ 11. Отвечая на ваш вопрос, этот код предназначен для относительно большого проекта FreeCAD, который в настоящее время использует MSVC2013 для создания сборок Windows. У меня нет машины с Windows. Я не знаю, почему мы используем MSVC2013, но я использую ваш вклад, чтобы спросить ответственного лица. Спасибо.

Abdullah Tahiri 05.04.2019 09:28

Другие вопросы по теме