constexpr kabuk değiştirmiş C++’ın en önemli anahtar sözcüklerinden biri. Üç ayrı yazımı bu anahtar sözcüğe ayıracağım. Bu okumakta olduğunuz birinci yazım.
constexpr anahtar sözcüğü “constant expression” (sabit ifadesi) sözcüklerinden uydurulmuş. constexpr anahtar sözcüğüyle tanıtılan bir varlık kod içinde sabit ifadesi olarak kullanılabiliyor. Derleyicinin derleme zamanında değerlerini bilme ya da hesaplama garantisi olan ifadelere sabit ifadesi dendiğini hatırlayın. constexpr anahtar sözcüğü hem bir değişkenin hem de bir işlevin tanımında kullanılabiliyor. constexpr anahtar sözcüğü ile tanımlanan işlevler ikinci yazımın konusu olacak. Şimdilik yalnızca constexpr değişkenlerle yetineceğim:
1 |
constexpr int x = 10; |
x değişkeni sabit ifadesi (constant expression) gereken her yerde kullanılabilir.
x, değeri hiç değişmeyecek bir değişken. Yani hayatta olduğu sürece hep aynı değerde kalacak. Bu açıdan bakıldığında constexpr anahtar sözcüğü const anahtar sözcüğünün anlamını da içeriyor.
x ifadesi bir dizi tanımında boyut ifadesi olarak kullanılabilir. Bir numaralandırma (enumaration) değeri olarak kullanılabilir. Bir switch deyiminin case ifadesi olabilir. Sabit parametreli (nontype template parameter) bir şablonun açılımında arguman olarak kullanılabilir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
template<int n> class Tclass { /// }; constexpr int x = 10; enum Color {White = 1, Blue = 5, Brown = 8, Magenta = x}; int main() { int a[x] = { 0 }; Tclass<x> y; // return 0; } |
constexpr ile tanıtılan bir değişkene bir sabit ifadesi ile ilk değer verilmeli ve derleyici bu kontrolü yapmakla yükümlü. constexpr bir değişkene ilk değer verilmemesi ya da sabit ifadesi olmayan bir ifade ile ilk değer verilmesi doğrudan sentaks hatası:
1 2 3 4 5 6 7 8 9 10 11 12 |
int func(); int main() { int ival = 10; constexpr int cx1; //geçersiz constexpr int cx2 = ival; //geçersiz constexpr int cx3 = func(); //geçersiz // return 0; } |
1 2 3 4 5 6 7 8 9 10 |
int main() { constexpr int x = 100; constexpr int primes[10] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 }; x++; //geçersiz primes[1] = 20; //geçersiz // return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int func(); int main() { const int x1 = func(); //geçerli const int x2 = 10; //geçerli constexpr int cx1 = x1; //geçersiz. x1 sabit ifadesi değil constexpr int cx2 = x2; //geçerli, x2 sabit ifadesi constexpr int cx3 = func(); //geçersiz, func() sabit ifadesi değil int a[x1]; //geçersiz, dizi boyutu sabit ifadesi değil int b[x2]; //geçerli, dizi boyutu sabit ifadesi. int c[cx3]; //geçerli, dizi boyutu sabit ifadesi. return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 |
class Myclass { constexpr int mx = 10; //geçersiz static constexpr int msx = 20; //geçerli /// }; constexpr int g = 10; //geçerli void func(constexpr int x) //geçersiz { constexpr int y = 10; //geçerli } |
1 |
constexpr const int x = 10; //geçerli ama const gereksiz |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
int main() { int x = 0; int y = 0; int *const p1 = &x; //p1 kendisi const bir gösterici //p1 is a const pointer. //p1 is top level const *p1 = 100; //geçerli, x = 100; p1 = &y; //geçersiz // const int *p2 = &x; //int const *p2 = &x; //aynı anlamda //p2 gösterdiği yer const gösterici //p2 is a pointer to const oject //p2 is low level const p2 = &y; //geçerli *p2 = 100; //geçersiz const int *const p3 = &x; //int const *const p3 = &x; //aynı anlamda //p3 gösterdiği yer const olan kendisi const gösterici //p2 is a const pointer to const oject //p2 is low level && top level consty p2 = &y; //geçersiz *p2 = 100; //geçersiz // } |
1 2 3 4 |
int g = 20; constexpr const int * p = &g; //constexpr int const * p = &g; //aynı anlamda |
Bu arada constexpr değişkenlere bir sabit ifadesi ile ilk değer verilmesi zorunlu olduğundan constexpr gösterici değişkenlere de sabit ifadesi olma özelliğine sahip adreslerle ilk değer verilmeli. Yerel değişkenlerin adresleri sabit ifadesi olarak kabul edilmiyor:
1 2 3 4 5 6 7 8 9 |
int g = 20; int main() { int x = 10; constexpr int *p1 = &g; //geçerli, &g sabit ifadesi. constexpr int *p2 = &x; //geçersiz, &x sabit ifadesi değil. // } |