Багато років пройшло з моменту появи нових стандартів C++, але досі трапляються системи у яких вони не підтримуються. У цій статті я розкажу, як за допомогою препроцесору визначити, чи підтримує компілятор потрібні мовні нововведення.
__cpluslus
Найбільш "правильним" є використання макросу __cpluslus
. Це значення, яке рівне року та місяцю прийняття стандарту у форматі yyyymmL
, зокрема:
- 199711L для C++98
- 201103L для C++11
- 201402L для C++14
Використання приблизно таке:
std::list<int> someList ;
#if (__cplusplus >= 201103L)
auto it = std::find(someList.begin(), someList.end(), 25);
#else
std::vector<int>::iterator it;
it = find (someList.begin(), someList.end(), 25);
#endif
Колись, дуже давно, цей макрос використовувався для того, щоб відрізнити компілятор C++ від чистого C; при цьому перевірка виконувалась просто на наявність. Якщо треба зберегти цю особливість, можна зробити так:
#ifndef __cplusplus
# error C++ is required
#elif __cplusplus >= 201103L
// do some C++0x code here
#endif
Деякі версії Microsoft Visual Studio не підтримували цей макрос (див. тут ).
Інші стандартні макроси
Для багатьох нововведень існує свій окремий макрос. Для лямбд це __cpp_lambdas
(а також ще пара варіантів для найновіших версій).
std::vector<int> c ;
#if defined( __cpp_lambdas )
std::for_each(c.begin(), c.end(), [](int i){ std::cout << i << ' '; });
#endif
Перелік усіх можливих макросів можна знайти на cppreference.com, також там можна знайти дати прийняття відповідних стандартів.
Boost
Як це завжди буває, у Boost є свій власний набір макросів , що визначають підтримку стандартів. Наприклад:
#if !defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
auto increment_lambda = [](boost::int32_t i){ accumulator += i; };
#endif
Застарілі версії gcc
Правильна реалізація __cplusplus
з'явилась у gcc 4.7. Якщо треба забезпечити підтримку для зовсім старих версій компілятора, слід використовувати конструкцію __GXX_EXPERIMENTAL_CXX0X
:
#if defined(__GXX_EXPERIMENTAL_CXX0X) || (__cplusplus >= 201103L)
#include <cstdint>
#else
#include <stdint.h>
#endif // defined
Хоча у такому специфічному випадку краще просто перевіряти версію компілятора за допомогою __GNUC__
та __GNUC_MINOR__
.
Ще немає коментарів