C ++ işlevi constexpr işaretlemek hiç kötü mü?


26

Çok önemsiz bir fonksiyon verildiğinde,

int transform(int val) {
    return (val + 7) / 8;
}

Değişkenleri constexprtanımlarken kullanmama izin verecek şekilde, bu işlevi bir işleve dönüştürmenin kolay olduğu çok açık olmalıdır constexpr:

constexpr int transform(int val) {
    return (val + 7) / 8;
}

Benim varsayım, bunun kesinlikle bir gelişme olduğudur, çünkü işlev hala constexprbağlam dışı olarak çağrılabilir ve şimdi derleme zamanı sabit değişkenlerini tanımlamaya yardımcı olmak için de kullanılabilir.

Sorum şu ki, bunun kötü bir fikir olduğu durumlar var mı? Bu fonksiyonu yaparak, bu fonksiyonun constexprbelirli bir durumda artık kullanılamayacağı veya yanlış davranacağı bir durumla karşılaşabilir miyim?


1
Aklıma gelen tek şey derleyici böceklerdi. Özyinelemeli bir constexpr işlev çağrısı gerçekten yavaş bir derleme adımına veya hatta bir derleyicinin bellek çökmesine neden olabilir.
Zan Lynx,

Yanıtlar:


19

Bu, yalnızca işlev ortak bir arabirimin parçasıysa ve API'nizin gelecekteki sürümlerini ikili uyumlu tutmak istiyorsanız önemlidir. Bu durumda, API'nizi nasıl geliştirmek istediğinizi ve gelecekteki değişiklikler için uzatma noktalarına ihtiyaç duyduğunuz yerleri dikkatlice düşünmeniz gerekir.

Bu bir constexprelemeyi değiştirilemez bir tasarım kararı haline getirir . API'nızda uyumsuz bir değişiklik yapmadan bu niteleyiciyi kaldıramazsınız. Ayrıca, bu işlevi nasıl uygulayabileceğinizi de sınırlar; örneğin, bu işlev içinde herhangi bir kayıt yapamazsınız. Her önemsiz işlev sonsuzlukta önemsiz kalamaz.

Bu, tercihen kendiliğinden saf işlevler olan ve derleme zamanında (örneğin, şablon metaprogramlama için) gerçekten yararlı olan işlevler constexpriçin kullanmanız gerektiği anlamına gelir . İşlevleri karmaşık hale getirmek iyi olmaz, çünkü şu anki uygulama tutarlı olabilir.

Derleme zamanı değerlendirmesinin gerekli olmadığı durumlarda, satır içi işlevler veya dahili bağlantıya sahip işlevler kullanmak daha uygun görünecektir constexpr. Bu değişkenlerin tümü, işlev gövdesinin “genel” olduğu ve çağrı konumu ile aynı derleme biriminde mevcut olduğu ortak noktaya sahiptir.

Söz konusu işlev istikrarlı, herkese açık bir API'nin parçası değilse, tasarımı istediğiniz zaman isteğe bağlı olarak değiştirebileceğinizden bu daha az sorun yaratır. Ancak, şimdi tüm arama sitelerini kontrol ettiğiniz için, “sadece durumunda” bir fonksiyonun işaretlenmesi gerekli değildir. Sen biliyorsun Bir constexpr bağlamında bu işlevi kullanıp kullanmadığınızı. Gereksiz yere kısıtlayıcı nitelikler eklemek, şaşkınlık olarak kabul edilebilir.


12

Bir işlevi aynı constexprzamanda bir satır içi işlevi olarak işaretlemek, § [dcl.constexpr] / 1:

Constexpr belirteci ile bildirilen bir işlev veya statik veri üyesi dolaylı olarak bir satır içi işlev veya değişkendir (7.1.6).

inlinesırayla, bu işlevin tanımını, kullanılabileceği her çeviri birimine eklemeniz gerektiği anlamına gelir. Bu temelde constexprişlevlerden birinin olması gerektiği anlamına gelir :

  1. bir çeviri biriminde kullanımı kısıtlanmışsa veya
  2. bir başlıkta tanımlanmıştır.

Bir başlıkta bildirmek ve bir kaynak dosyada tanımlamak istediğiniz en tipik işlevler (ve bunları kullanan herhangi bir şey yalnızca başlığı içerir, o zaman o kaynağın nesne dosyasına karşı bağlanır) constexprçalışmaz.

Teoride, her şeyi başlıklara taşıyabileceğinizi ve sadece tüm başlıkları içeren tek bir kaynak dosyasına sahip olabileceğinizi varsayalım, ancak bu derleme zamanlarını büyük ölçüde incitir ve çoğu ciddi proje için çok fazla miktarda bellek derlemek ister.

Bir constexprfonksiyon bazı şekillerde de sınırlıdır, bu nedenle bazı fonksiyonlar için bir seçenek olmayabilir. Kısıtlamalar şunları içerir:

  1. sanal fonksiyonlar olamaz olmak constexpr.
  2. onun geri dönüş tipi 'değişmez tür' olmalıdır (örneğin, trival olmayan veya dtorsu olmayan nesneler yok).
  3. parametrelerinin tümü değişmez türler olmalıdır.
  4. fonksiyon gövdesi bir tryblok içeremez .
  5. değişmez bir türün değişken tanımını veya statik veya iş parçacığı saklama süresi olan herhangi bir şeyi içeremez.

Bir çiftin üstünden atladım, belirsiz şeyleri atladım (örneğin, ayrıca gotobir asmdeyim içeremez ), ama siz bir fikre kapılıyorsunuz - epeyce şey için, işe yaramayacak.

Alt satır: evet, bunun kötü bir fikir olacağı birkaç durum var.


"sanal olmamalıdır (C ++ 20'ye kadar)" Sanal bir fonksiyonun nasıl karmaşık olabileceğini merak ediyorum? Derleyiciler ne yapar?
chaosink
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.