Як перевірити підтримку C ++ 11?


104

Чи є спосіб виявити під час компіляції, якщо компілятор підтримує певні функції C ++ 11? Наприклад, щось подібне:

#ifndef VARIADIC_TEMPLATES_SUPPORTED

#error "Your compiler doesn't support variadic templates.  :("

#else

template <typename... DatatypeList>
class Tuple
{
    // ...
}

#endif

2
У вас може бути заголовок під назвою "assert_variadic_template_support.hpp", який ви можете включити і в межах зробити щось на кшталт template <typename... Test> struct compiler_must_support_variadic_templates;. Помилка синтаксису швидко виявить проблему. (Як і вбік, правильне повідомлення про помилку набагато краще.)
GManNickG

Правильний спосіб вирішення цієї проблеми - це тест налаштування.
Джозеф Гарвін

Відповіді:


125

Існує константа з ім'ям , __cplusplusщо компілятори C ++ слід встановити в версії C ++ стандарт підтримується побачити це

#if __cplusplus <= 199711L
  #error This library needs at least a C++11 compliant compiler
#endif

В Visual Studio 2010 SP1 він встановлений у 199711L, але я не знаю, чи будуть постачальники настільки сміливими, щоб збільшити його, якщо вони просто мають (часткову) підтримку рівня компілятора порівняно зі стандартною бібліотекою C ++ зі всіма змінами C ++ 11 .

Отже, визначення Boost, згадані в іншій відповіді, залишаються єдиним розумним способом з'ясувати, чи є, наприклад, підтримка C ++ 11 потоків та інших конкретних частин стандарту.


37
C ++ 11 встановлює значення __cplusplusдля 201103L. Це підтверджує повне відповідність стандарту 2011 року; це не розповідає про часткове розширення відповідності або розширення компілятора. Якщо __cplusplusвстановлено значення 201103L, то або компілятор повністю відповідає, або він бреше вам. Якщо це не так, то ви не можете реально сказати, які функції він підтримує.
Кіт Томпсон

1
g ++ 4.7.x (і, мабуть, новіший) встановлює це, коли -std=c++11опція задана (може також з -std=gnu++11). Вони роблять це, навіть якщо вони не зовсім повноцінні (4,8 зближує нас). Примітка. Існує розрив між тим, що підтримує компілятор, і наявним у стандартній бібліотеці. У обох 4.7.x та 4.8.x наразі відсутня підтримка регулярних виразів - але це бібліотека, а не функція компілятора.
Натан Ернст

1
Цікаво, чому це не прийнята відповідь. Також ви можете використати цю пропозицію для подальшого покращення своєї відповіді, це дуже добре.
Іхароб Аль Асімі

1
@KeithThompson Для мене і Code: Blocks і Visual Studio встановили значення __cplusplusдля 199711Lдля C ++ 11.
Дональд Дак

3
@DonaldDuck: Строго кажучи, ні, вони ні. Компілятор , який встановлює , __cplusplusщоб 199711Lне є в відповідно C ++ 11 компілятора. У них, ймовірно, є варіанти, щоб змусити їх вести себе правильно.
Кіт Томпсон

39

Як зазначено у стандарті C ++ 11 (§iso.16.8):

Ім'я __cplusplus визначається значенням 201103L при складанні одиниці перекладу C ++.

За допомогою значення цього макроса ви можете перевірити, чи компілятор сумісний із C ++ 11.

Тепер, якщо ви шукаєте стандартний спосіб перевірити, чи підтримує компілятор якийсь підмножина функцій C ++ 11, я думаю, що немає стандартного, портативного способу; ви можете перевірити документацію на компілятори або файли заголовків std-бібліотеки, щоб отримати більше інформації.


2
Наприклад, static_assert підтримується у VS2010 та у всіх копіратах c ++ 11. Отже, якщо ви перевірите, чи є значення __cplusplus більшим або рівним встановленому у VS2010 (тобто> = 199711L), ви можете бути в порядку.
Паоло М

33

Я знаю, що це дуже давнє запитання, але це питання, можливо, часто можна побачити, а відповіді трохи застаріли.

Нові компілятори зі стандартом C ++ 14 мають стандартний спосіб перевірки функцій, включаючи функції C ++ 11. Вичерпна сторінка знаходиться на веб-сторінці https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations

Підсумовуючи, кожна функція має стандартний макрос, який ви можете перевірити #ifdef. Наприклад, для перевірки визначених користувачем літералів ви можете використовувати

#ifdef __cpp_user_defined_literals

1
Я цього не знав. Я думаю, що ця проста функція заходить пізно, але все ще може бути дуже корисною, особливо __has_include()макрос.
prapin

22

Для перевірки підтримки C ++ 14 та інших. Тестування на GCC 5.2.1.

#include <iostream>

int main(){
        #if __cplusplus==201402L
        std::cout << "C++14" << std::endl;
        #elif __cplusplus==201103L
        std::cout << "C++11" << std::endl;
        #else
        std::cout << "C++" << std::endl;
        #endif

        return 0;
}

17

Ви можете скористатися цим:

#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
    cout << "C++11 is supported";
#else
    cout << "C++11 is not supported";
#endif

Для C ++ 11 більшість компіляторів, крім Visual Studio, встановлюють __cplusplusмакрос у 201103L, але будь-яка версія Visual Studio встановлює його, при 199711Lякому це значення, яке використовується для інших компіляторів до C ++ 11. Цей код порівнює _cplusplusмакрос з 201103Lусіма компіляторами, крім Visual Studio, і якщо компілятором є Visual Studio, він перевіряє, чи версія Visual Studio пізніше 2015 року, перша версія Visual Studio, яка повністю підтримує C ++ 11 (для Visual Студія 2015, _MSC_VERмакрос має значення 1900, див. Цю відповідь ).


1
Ця відповідь невірна. Для g++ -std=c++98GCC 4.8 він невірно друкує C++11 is supported.
пт

1
@pts Вибачте, просто помилка. Це слід виправити зараз.
Дональд Дак

7

Якщо ви не хочете використовувати Boost.Config і вам потрібно протестувати компілятори, які підтримують C ++ 11, то перевірка значення константи __cplusplusбуде зроблена . Однак компілятор може підтримувати більшість популярних функцій стандарту C ++ 11, проте він не підтримує всі технічні характеристики. Якщо ви хочете ввімкнути підтримку конкретних компіляторів Visual Studio, які ще не на 100% відповідають специфікаціям C ++ 11, то використовуйте наступний фрагмент коду, який дозволяє компілювати в Visual Studio 2013:

#if defined(_MSC_VER)
#   if _MSC_VER < 1800 
#       error This project needs atleast Visual Studio 2013
#   endif
#elif __cplusplus <= 199711L
#   error This project can only be compiled with a compiler that supports C++11
#endif

Повний перелік версій компілятора для Visual Studio представлений у розділі Як виявити, чи я компілюю код з Visual Studio 2008


6

У традиційному світі Linux / Unix autoconf традиційно використовується для перевірки на наявність бібліотек та функцій компілятора та помилок, розміщуючи їх у config.h, який ви використовуєте у своїх файлах за потребою.


2
Так, autoconf можна використовувати для тестування функцій, але ви повинні змусити його генерувати відповідний макрос для помилок або успіхів, які потім можуть бути перевірені кодом вище. Тож ця відповідь сама по собі не додає жодної інформації.
Мартін Йорк

3
@LokiAstari: Autoconf не працює. Autoconf надає макроси, які дозволяють вашому сценарію налаштування компілювати тестовий вихідний файл і встановити #define на 0 або 1 на основі успіху компіляції. відповідь diverscuba23 надає інформацію, вказуючи, що ОП досягає неоптимального вирішення реальної проблеми.
Джозеф Гарвін


1

Коли ви перевіряєте наявність бібліотеки C ++ 11 (не мовна функція), наприклад, <array>заголовок, ви можете #if __has_include(<array>).

Іноді перевірка #if __cplusplus >= 201103Lскаже вам, що ви використовуєте C ++ 11, але в інших настройках, таких як стандартна установка версії бібліотеки в Xcode, все ще не можуть бути доступні нові бібліотеки (більшість з них доступні під різними іменами, тобто <tr1/array>)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.