C++20: Özellik testi makrolarıyla derleyici özellik tespiti

Adanali

Active member
C++20: Özellik testi makrolarıyla derleyici özellik tespiti


  1. C++20: Özellik testi makrolarıyla derleyici özellik tespiti

C++20, hangi özellikleri desteklediğini görmek için kullanılan derleyiciyi inceleyen özellik test makrolarıyla birlikte gelir.


Duyuru









En son C++ özelliklerini deneyen herkes sıklıkla hata mesajları alır. Şimdi şu soru ortaya çıkıyor: Bütün bunların sorumlusu kim?

  1. Siz de mi hata yaptınız?
  2. Kullanılan derleyici bu işlevselliği destekliyor mu?
  3. Bir derleyici hatası mı oluştu?






Rainer Grimm uzun yıllardır yazılım mimarı, ekip ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanıyor, aynı zamanda özel konferanslarda sık sık konuşmaktan da hoşlanıyor. Modern C++ adlı blogunda C++ tutkusunu yoğun bir şekilde ele alıyor.







Seçenek 3 nadir görülen bir durumdur, dolayısıyla yalnızca bir soruyu yanıtlamanız gerekir: Derleyici bu özelliği destekliyor mu?

Bu soruyu cppreference ve özellik testi makrolarıyla yanıtlamak kolaydır.

C++ derleyici desteği


Çoğu zaman olduğu gibi cppreference.com/compiler_support, C++11'den C++26'ya kadar standartlar da dahil olmak üzere dil ve kitaplıklar hakkındaki temel sorulara yanıtlar sağlar.

Aşağıdaki tablolarda C++26 standardına yönelik çekirdek kitaplığa ve dil desteğine genel bir bakış sunulmaktadır.

Temel C++26 dili









C++26 kütüphanesi









Cevaplar yeterince spesifik değilse C++20'deki makro test özelliği yardımcı olacaktır.

Özellik testi makroları


Başlıklı <version> derleyiciye C++ 11 veya üzeri desteğini sorabilirsiniz. Ana dilin veya kütüphanenin niteliklerini, özelliklerini sorabilirsiniz. <version> işlevsellik uygulandıkça sayıları artan 300'den fazla makro tanımlamıştır. Sayı, özelliğin taslak C++ standartlarına eklendiği yılı ve ayı temsil eder. Bunlar için rakamlar static_assert, Lambdas VE Concepts.


__cpp_static_assert 200410L&#13;
__cpp_lambdas 200907L&#13;
__cpp_concepts 201907L


Özellik Testi Makroları sayfası tüm makroları listeler.

Cppreference'tan uyarladığım ve uyarladığım aşağıdaki program, tüm makroları ana C++20 dilinde görüntülüyor. Bayrak /Zc:__cplusplus Windows'ta özellik testi makrosunu etkinleştirin.


// featureTesting20.cpp&#13;
// from cppreference.com&#13;
&#13;
#if __cplusplus < 201100&#13;
# error "C++11 or better is required"&#13;
#endif&#13;
&#13;
#include <algorithm>&#13;
#include <cstring>&#13;
#include <iomanip>&#13;
#include <iostream>&#13;
#include <string>&#13;
&#13;
#ifdef __has_include&#13;
# if __has_include(<version>)&#13;
# include <version>&#13;
# endif&#13;
#endif&#13;
&#13;
#define COMPILER_FEATURE_VALUE(value) #value&#13;
#define COMPILER_FEATURE_ENTRY(name) { #name, COMPILER_FEATURE_VALUE(name) },&#13;
&#13;
#ifdef __has_cpp_attribute&#13;
# define COMPILER_ATTRIBUTE_VALUE_AS_STRING(s) #s&#13;
# define COMPILER_ATTRIBUTE_AS_NUMBER(x) COMPILER_ATTRIBUTE_VALUE_AS_STRING(x)&#13;
# define COMPILER_ATTRIBUTE_ENTRY(attr) &#13;
{ #attr, COMPILER_ATTRIBUTE_AS_NUMBER(__has_cpp_attribute(attr)) },&#13;
#else&#13;
# define COMPILER_ATTRIBUTE_ENTRY(attr) { #attr, "_" },&#13;
#endif&#13;
&#13;
// Change these options to print out only necessary info.&#13;
static struct PrintOptions {&#13;
constexpr static bool titles = 1;&#13;
constexpr static bool attributes = 1;&#13;
constexpr static bool general_features = 1;&#13;
constexpr static bool core_features = 1;&#13;
constexpr static bool lib_features = 1;&#13;
constexpr static bool supported_features = 1;&#13;
constexpr static bool unsupported_features = 1;&#13;
constexpr static bool sorted_by_value = 0;&#13;
constexpr static bool cxx11 = 1;&#13;
constexpr static bool cxx14 = 1;&#13;
constexpr static bool cxx17 = 1;&#13;
constexpr static bool cxx20 = 1;&#13;
constexpr static bool cxx23 = 0;&#13;
} print;&#13;
&#13;
struct CompilerFeature {&#13;
CompilerFeature(const char* name = nullptr, const char* value = nullptr)&#13;
: name(name), value(value) {}&#13;
const char* name; const char* value;&#13;
};&#13;
&#13;
static CompilerFeature cxx20[] = {&#13;
COMPILER_FEATURE_ENTRY(__cpp_aggregate_paren_init)&#13;
COMPILER_FEATURE_ENTRY(__cpp_char8_t)&#13;
COMPILER_FEATURE_ENTRY(__cpp_concepts)&#13;
COMPILER_FEATURE_ENTRY(__cpp_conditional_explicit)&#13;
COMPILER_FEATURE_ENTRY(__cpp_consteval)&#13;
COMPILER_FEATURE_ENTRY(__cpp_constexpr)&#13;
COMPILER_FEATURE_ENTRY(__cpp_constexpr_dynamic_alloc)&#13;
COMPILER_FEATURE_ENTRY(__cpp_constexpr_in_decltype)&#13;
COMPILER_FEATURE_ENTRY(__cpp_constinit)&#13;
COMPILER_FEATURE_ENTRY(__cpp_deduction_guides)&#13;
COMPILER_FEATURE_ENTRY(__cpp_designated_initializers)&#13;
COMPILER_FEATURE_ENTRY(__cpp_generic_lambdas)&#13;
COMPILER_FEATURE_ENTRY(__cpp_impl_coroutine)&#13;
COMPILER_FEATURE_ENTRY(__cpp_impl_destroying_delete)&#13;
COMPILER_FEATURE_ENTRY(__cpp_impl_three_way_comparison)&#13;
COMPILER_FEATURE_ENTRY(__cpp_init_captures)&#13;
COMPILER_FEATURE_ENTRY(__cpp_modules)&#13;
COMPILER_FEATURE_ENTRY(__cpp_nontype_template_args)&#13;
COMPILER_FEATURE_ENTRY(__cpp_using_enum)&#13;
};&#13;
&#13;
&#13;
constexpr bool is_feature_supported(const CompilerFeature& x) {&#13;
return x.value[0] != '_' && x.value[0] != '0' ;&#13;
}&#13;
&#13;
inline void print_compiler_feature(const CompilerFeature& x) {&#13;
constexpr static int max_name_length = 44; //< Update if necessary&#13;
std::string value{ is_feature_supported(x) ? x.value : "------" };&#13;
if (value.back() == 'L') value.pop_back(); //~ 201603L -> 201603&#13;
// value.insert(4, 1, '-'); //~ 201603 -> 2016-03&#13;
if ( (print.supported_features && is_feature_supported(x))&#13;
|| (print.unsupported_features && !is_feature_supported(x))) {&#13;
std::cout << std::left << std::setw(max_name_length)&#13;
<< x.name << " " << value << 'n';&#13;
}&#13;
}&#13;
&#13;
template<size_t N>&#13;
inline void show(char const* title, CompilerFeature (&features)[N]) {&#13;
if (print.titles) {&#13;
std::cout << 'n' << std::left << title << 'n';&#13;
}&#13;
if (print.sorted_by_value) {&#13;
std::sort(std::begin(features), std::end(features),&#13;
[](CompilerFeature const& lhs, CompilerFeature const& rhs) {&#13;
return std::strcmp(lhs.value, rhs.value) < 0;&#13;
});&#13;
}&#13;
for (const CompilerFeature& x : features) {&#13;
print_compiler_feature(x);&#13;
}&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
if (print.cxx20 && print.core_features) show("C++20 CORE", cxx20);&#13;
&#13;
}


Aşağıdaki Derleyici Gezgini ekran görüntüleri GCC 8.1, 10.1 ve 14.1 derleyicilerinin C++20 desteğini göstermektedir.




















Bir sonraki adım nedir?


Bir sonraki yazımda C++23 yolculuğuma devam edeceğim.


(Ben)
 
Üst