C ++ 20: İşlevsellik testi makro ile derleyicinin işlevlerini belirleyin
C ++ 20, işlevsellik testlerinin makresini getirir, bu nedenle desteklediği özelliklerin kullandığı derleyiciyi inceler.
En son C ++ özelliklerini denerseniz, genellikle hata mesajları alırsınız. Şimdi soru ortaya çıkıyor: Bundan kim sorumlu?
Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.
Seçenek 3 nadiren oluşur, bu yüzden sadece bir soruyu cevaplamanız gerekir: derleyici bu işlevi destekliyor mu?
Bu sorunun cpprerereeanice ve işlevsellik testlerinin makresi sayesinde cevaplaması kolaydır.
C ++ derleyici desteği
CppReference.com/compiler_support, C ++ 26'ya kadar C ++ 11 standartları da dahil olmak üzere temel dil ve kütüphane hakkında sorulara cevap verir.
Aşağıdaki tablolar, ana dil desteğine ve C ++ 26 standardı için kütüphaneye genel bir bakış sağlar.
C ++ 26 Çekirdek Dil
C ++ 26 Kütüphane
Cevaplar yeterince spesifik değilse, C ++ 20'de işlevsellik testlerinin makresi yardımcı olur.
İşlevsellik testlerinin makro
Başlık ile <version> Derleyiciden C ++ 11 veya daha yüksek desteğini isteyebilirsiniz. Ana dil veya kütüphanenin özellikleri, özellikleri sorabilirsiniz. <version> İşlev uygulandığında bir sayıya genişleyen 300'den fazla makro tanımlamıştır. Sayı, C ++ standart tasarım işlevinin eklendiği yıl ve ay içindir. Bunlar sayıları static_assert, Lambdas VE Concepts.
__cpp_static_assert 200410L
__cpp_lambdas 200907L
__cpp_concepts 201907L
İşlev Testi Makro Makro, tüm makroları listeler.
CPPReference tarafından benimsenen ve uyarladığım aşağıdaki program, ana dil C ++ 20'nin tüm makrolarını gösteriyor. Bayrak /Zc:__cplusplus Windows altındaki makro işlevsellik testini etkinleştirin.
// featureTesting20.cpp
// from cppreference.com
#if __cplusplus < 201100
# error "C++11 or better is required"
#endif
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <string>
#ifdef __has_include
# if __has_include(<version>)
# include <version>
# endif
#endif
#define COMPILER_FEATURE_VALUE(value) #value
#define COMPILER_FEATURE_ENTRY(name) { #name, COMPILER_FEATURE_VALUE(name) },
#ifdef __has_cpp_attribute
# define COMPILER_ATTRIBUTE_VALUE_AS_STRING(s) #s
# define COMPILER_ATTRIBUTE_AS_NUMBER(x) COMPILER_ATTRIBUTE_VALUE_AS_STRING(x)
# define COMPILER_ATTRIBUTE_ENTRY(attr)
{ #attr, COMPILER_ATTRIBUTE_AS_NUMBER(__has_cpp_attribute(attr)) },
#else
# define COMPILER_ATTRIBUTE_ENTRY(attr) { #attr, "_" },
#endif
// Change these options to print out only necessary info.
static struct PrintOptions {
constexpr static bool titles = 1;
constexpr static bool attributes = 1;
constexpr static bool general_features = 1;
constexpr static bool core_features = 1;
constexpr static bool lib_features = 1;
constexpr static bool supported_features = 1;
constexpr static bool unsupported_features = 1;
constexpr static bool sorted_by_value = 0;
constexpr static bool cxx11 = 1;
constexpr static bool cxx14 = 1;
constexpr static bool cxx17 = 1;
constexpr static bool cxx20 = 1;
constexpr static bool cxx23 = 0;
} print;
struct CompilerFeature {
CompilerFeature(const char* name = nullptr, const char* value = nullptr)
: name(name), value(value) {}
const char* name; const char* value;
};
static CompilerFeature cxx20[] = {
COMPILER_FEATURE_ENTRY(__cpp_aggregate_paren_init)
COMPILER_FEATURE_ENTRY(__cpp_char8_t)
COMPILER_FEATURE_ENTRY(__cpp_concepts)
COMPILER_FEATURE_ENTRY(__cpp_conditional_explicit)
COMPILER_FEATURE_ENTRY(__cpp_consteval)
COMPILER_FEATURE_ENTRY(__cpp_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_constexpr_dynamic_alloc)
COMPILER_FEATURE_ENTRY(__cpp_constexpr_in_decltype)
COMPILER_FEATURE_ENTRY(__cpp_constinit)
COMPILER_FEATURE_ENTRY(__cpp_deduction_guides)
COMPILER_FEATURE_ENTRY(__cpp_designated_initializers)
COMPILER_FEATURE_ENTRY(__cpp_generic_lambdas)
COMPILER_FEATURE_ENTRY(__cpp_impl_coroutine)
COMPILER_FEATURE_ENTRY(__cpp_impl_destroying_delete)
COMPILER_FEATURE_ENTRY(__cpp_impl_three_way_comparison)
COMPILER_FEATURE_ENTRY(__cpp_init_captures)
COMPILER_FEATURE_ENTRY(__cpp_modules)
COMPILER_FEATURE_ENTRY(__cpp_nontype_template_args)
COMPILER_FEATURE_ENTRY(__cpp_using_enum)
};
constexpr bool is_feature_supported(const CompilerFeature& x) {
return x.value[0] != '_' && x.value[0] != '0' ;
}
inline void print_compiler_feature(const CompilerFeature& x) {
constexpr static int max_name_length = 44; //< Update if necessary
std::string value{ is_feature_supported(x) ? x.value : "------" };
if (value.back() == 'L') value.pop_back(); //~ 201603L -> 201603
// value.insert(4, 1, '-'); //~ 201603 -> 2016-03
if ( (print.supported_features && is_feature_supported(x))
|| (print.unsupported_features && !is_feature_supported(x))) {
std::cout << std::left << std::setw(max_name_length)
<< x.name << " " << value << 'n';
}
}
template<size_t N>
inline void show(char const* title, CompilerFeature (&features)[N]) {
if (print.titles) {
std::cout << 'n' << std::left << title << 'n';
}
if (print.sorted_by_value) {
std::sort(std::begin(features), std::end(features),
[](CompilerFeature const& lhs, CompilerFeature const& rhs) {
return std::strcmp(lhs.value, rhs.value) < 0;
});
}
for (const CompilerFeature& x : features) {
print_compiler_feature(x);
}
}
int main() {
if (print.cxx20 && print.core_features) show("C++20 CORE", cxx20);
}
Aşağıdaki derleyici Explorer ekran görüntüleri, GCC derleyicisinin 8.1, 10.1 ve 14.1'in C ++ 20 desteğini göstermektedir.
Sırada ne var?
Bir sonraki makalemde C ++ 23'teki yolculuğuma devam ediyorum.
(RME)
C ++ 20: İşlevsellik testi makro ile derleyicinin işlevlerini belirleyin
C ++ 20, işlevsellik testlerinin makresini getirir, bu nedenle desteklediği özelliklerin kullandığı derleyiciyi inceler.

En son C ++ özelliklerini denerseniz, genellikle hata mesajları alırsınız. Şimdi soru ortaya çıkıyor: Bundan kim sorumlu?
- Yalnız bir hata yaptın mı?
- Derleyici bu işlevi kullandı mı?
- Bir derleyici hata oluştu mu?

Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.
Seçenek 3 nadiren oluşur, bu yüzden sadece bir soruyu cevaplamanız gerekir: derleyici bu işlevi destekliyor mu?
Bu sorunun cpprerereeanice ve işlevsellik testlerinin makresi sayesinde cevaplaması kolaydır.
C ++ derleyici desteği
CppReference.com/compiler_support, C ++ 26'ya kadar C ++ 11 standartları da dahil olmak üzere temel dil ve kütüphane hakkında sorulara cevap verir.
Aşağıdaki tablolar, ana dil desteğine ve C ++ 26 standardı için kütüphaneye genel bir bakış sağlar.
C ++ 26 Çekirdek Dil

C ++ 26 Kütüphane

Cevaplar yeterince spesifik değilse, C ++ 20'de işlevsellik testlerinin makresi yardımcı olur.
İşlevsellik testlerinin makro
Başlık ile <version> Derleyiciden C ++ 11 veya daha yüksek desteğini isteyebilirsiniz. Ana dil veya kütüphanenin özellikleri, özellikleri sorabilirsiniz. <version> İşlev uygulandığında bir sayıya genişleyen 300'den fazla makro tanımlamıştır. Sayı, C ++ standart tasarım işlevinin eklendiği yıl ve ay içindir. Bunlar sayıları static_assert, Lambdas VE Concepts.
__cpp_static_assert 200410L
__cpp_lambdas 200907L
__cpp_concepts 201907L
İşlev Testi Makro Makro, tüm makroları listeler.
CPPReference tarafından benimsenen ve uyarladığım aşağıdaki program, ana dil C ++ 20'nin tüm makrolarını gösteriyor. Bayrak /Zc:__cplusplus Windows altındaki makro işlevsellik testini etkinleştirin.
// featureTesting20.cpp
// from cppreference.com
#if __cplusplus < 201100
# error "C++11 or better is required"
#endif
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <string>
#ifdef __has_include
# if __has_include(<version>)
# include <version>
# endif
#endif
#define COMPILER_FEATURE_VALUE(value) #value
#define COMPILER_FEATURE_ENTRY(name) { #name, COMPILER_FEATURE_VALUE(name) },
#ifdef __has_cpp_attribute
# define COMPILER_ATTRIBUTE_VALUE_AS_STRING(s) #s
# define COMPILER_ATTRIBUTE_AS_NUMBER(x) COMPILER_ATTRIBUTE_VALUE_AS_STRING(x)
# define COMPILER_ATTRIBUTE_ENTRY(attr)
{ #attr, COMPILER_ATTRIBUTE_AS_NUMBER(__has_cpp_attribute(attr)) },
#else
# define COMPILER_ATTRIBUTE_ENTRY(attr) { #attr, "_" },
#endif
// Change these options to print out only necessary info.
static struct PrintOptions {
constexpr static bool titles = 1;
constexpr static bool attributes = 1;
constexpr static bool general_features = 1;
constexpr static bool core_features = 1;
constexpr static bool lib_features = 1;
constexpr static bool supported_features = 1;
constexpr static bool unsupported_features = 1;
constexpr static bool sorted_by_value = 0;
constexpr static bool cxx11 = 1;
constexpr static bool cxx14 = 1;
constexpr static bool cxx17 = 1;
constexpr static bool cxx20 = 1;
constexpr static bool cxx23 = 0;
} print;
struct CompilerFeature {
CompilerFeature(const char* name = nullptr, const char* value = nullptr)
: name(name), value(value) {}
const char* name; const char* value;
};
static CompilerFeature cxx20[] = {
COMPILER_FEATURE_ENTRY(__cpp_aggregate_paren_init)
COMPILER_FEATURE_ENTRY(__cpp_char8_t)
COMPILER_FEATURE_ENTRY(__cpp_concepts)
COMPILER_FEATURE_ENTRY(__cpp_conditional_explicit)
COMPILER_FEATURE_ENTRY(__cpp_consteval)
COMPILER_FEATURE_ENTRY(__cpp_constexpr)
COMPILER_FEATURE_ENTRY(__cpp_constexpr_dynamic_alloc)
COMPILER_FEATURE_ENTRY(__cpp_constexpr_in_decltype)
COMPILER_FEATURE_ENTRY(__cpp_constinit)
COMPILER_FEATURE_ENTRY(__cpp_deduction_guides)
COMPILER_FEATURE_ENTRY(__cpp_designated_initializers)
COMPILER_FEATURE_ENTRY(__cpp_generic_lambdas)
COMPILER_FEATURE_ENTRY(__cpp_impl_coroutine)
COMPILER_FEATURE_ENTRY(__cpp_impl_destroying_delete)
COMPILER_FEATURE_ENTRY(__cpp_impl_three_way_comparison)
COMPILER_FEATURE_ENTRY(__cpp_init_captures)
COMPILER_FEATURE_ENTRY(__cpp_modules)
COMPILER_FEATURE_ENTRY(__cpp_nontype_template_args)
COMPILER_FEATURE_ENTRY(__cpp_using_enum)
};
constexpr bool is_feature_supported(const CompilerFeature& x) {
return x.value[0] != '_' && x.value[0] != '0' ;
}
inline void print_compiler_feature(const CompilerFeature& x) {
constexpr static int max_name_length = 44; //< Update if necessary
std::string value{ is_feature_supported(x) ? x.value : "------" };
if (value.back() == 'L') value.pop_back(); //~ 201603L -> 201603
// value.insert(4, 1, '-'); //~ 201603 -> 2016-03
if ( (print.supported_features && is_feature_supported(x))
|| (print.unsupported_features && !is_feature_supported(x))) {
std::cout << std::left << std::setw(max_name_length)
<< x.name << " " << value << 'n';
}
}
template<size_t N>
inline void show(char const* title, CompilerFeature (&features)[N]) {
if (print.titles) {
std::cout << 'n' << std::left << title << 'n';
}
if (print.sorted_by_value) {
std::sort(std::begin(features), std::end(features),
[](CompilerFeature const& lhs, CompilerFeature const& rhs) {
return std::strcmp(lhs.value, rhs.value) < 0;
});
}
for (const CompilerFeature& x : features) {
print_compiler_feature(x);
}
}
int main() {
if (print.cxx20 && print.core_features) show("C++20 CORE", cxx20);
}
Aşağıdaki derleyici Explorer ekran görüntüleri, GCC derleyicisinin 8.1, 10.1 ve 14.1'in C ++ 20 desteğini göstermektedir.



Sırada ne var?
Bir sonraki makalemde C ++ 23'teki yolculuğuma devam ediyorum.
(RME)