modül arayüzlerinde satır içi anlam


24

Başlık dosyasını düşünün:

class T
{
private:
  int const ID;

public:
  explicit T(int const ID_) noexcept : ID(ID_) {}

  int GetID() const noexcept { return ID; }
};

Veya alternatif olarak:

class T
{
private:
  int const ID;

public:
  explicit T(int const ID_) noexcept;

  int GetID() const noexcept;
};

inline T::T(int const ID_) noexcept : ID(ID_) {}

inline int T::GetID() const noexcept { return ID; }

Bir ön modül dünyasında, bu başlıklar ODR ihlali olmaksızın çoklu TU'ya metinsel olarak dahil edilebilir. Ayrıca, ilgili üye işlevleri nispeten küçük olduğu için, derleyici muhtemelen bu işlevleri "satır içi" (kullanırken işlev çağrılarından kaçınır) veya hatta bazı örnekleri Ttamamen optimize eder .

C ++ 20'nin bittiği toplantıyla ilgili son bir raporda , aşağıdaki ifadeyi okuyabilirim:

inlineModül arabirimlerindeki anlamını açıklığa kavuşturduk : amaç, açıkça belirtilmeyen inlineişlev gövdelerinin, bu işlev gövdeleri modül arabiriminde görünse bile bir modülün ABI'sının bir parçası olmamasıdır. Modül yazarlarına ABI'leri üzerinde daha fazla kontrol sağlamak için modül arayüzlerinde sınıf gövdelerinde tanımlanan üye işlevler artık örtük değildir inline.

Yanlış yaptığımdan emin değilim. Bu, bir modül dünyasında, derleyicinin işlev çağrılarını optimize edebilmesi için inline, sınıfta tanımlanmışlar gibi onlara açıklama eklememiz gerektiği anlamına mı geliyor ?

Öyleyse, aşağıdaki modül arayüzü yukarıdaki başlıklara eşdeğer olur mu?

export module M;

export
class T
{
private:
  int const ID;

public:
  inline explicit T(int const ID_) noexcept : ID(ID_) {}

  inline int GetID() const noexcept { return ID; }
};

Hala modül desteğine sahip bir derleyicim olmasa da inline, gelecekteki yeniden düzenlemeyi en aza indirmek için uygun olduğunda böyle kullanmaya başlamak istiyorum.

Yanıtlar:


11

Bu, bir modül dünyasında, derleyicinin işlev çağrılarını optimize edebilmesi için inline, sınıfta tanımlanmışlar gibi onlara açıklama eklememiz gerektiği anlamına mı geliyor ?

Bir dereceye kadar.

Inlining bir "sanki" optimizasyonudur ve derleyici yeterince zeki ise çeviri birimleri arasında bile inlinleme olabilir.

Bununla birlikte, tek bir çeviri birimi içinde çalışırken satır içi işlem en kolay yöntemdir. Bu nedenle, kolay inlinesatırlamayı teşvik etmek için, tanımlanmış bir fonksiyonun tanımının, kullanıldığı herhangi bir çeviri biriminde sunulması gerekir. Bu, derleyicinin kesinlikle satır içi olacağı (veya kesinlikle inlinekalifiye olmayan herhangi bir işlevi satır içi yapamayacağı) anlamına gelmez, ancak satır içi işlemde satır içi işlemde bir TU içinde gerçekleştiği için işleri satır içi süreçte çok daha kolay hale getirir.

Bir modül içinde, modül öncesi bir dünyada tanımlanan sınıf üyesi tanımları inlinedolaylı olarak bildirilir . Neden? Çünkü tanım sınıf içinde. Modül öncesi bir dünyada TU'lar arasında paylaşılan sınıf tanımları metin içerme yoluyla paylaşılır. Bu nedenle bir sınıfta tanımlanan üyeler, bu TU'lar arasında paylaşılan başlıkta tanımlanacaktır. Birden fazla TU aynı sınıfı kullanıyorsa, bu çoklu TU'lar sınıf tanımını ve başlıkta beyan edilen üyelerinin tanımını dahil ederek bunu yaparlar.

Yani, tanımı yine de dahil ediyorsunuz , neden yapmıyorsunuz inline?

Tabii ki, bu bir fonksiyonun tanımının artık sınıf metninin bir parçası olduğu anlamına gelir. Üstbilgide bildirilen bir üyenin tanımını değiştirirseniz, bu üstbilgiyi içeren her dosyanın yinelemeli olarak yeniden derlenmesi zorlanır. Sınıfın arabiriminin kendisi değişmese bile, yeniden derleme yapmanız gerekir. Dolayısıyla, bu tür işlevleri örtük inlineolarak yapmak bunu değiştirmez, bu yüzden bunu da yapabilirsiniz.

Bunu bir modül öncesi dünyada önlemek için, C ++ dosyasındaki üyeyi tanımlamanız yeterlidir, bu da diğer dosyalara dahil edilmez. Kolay satır içi veri kaybedersiniz, ancak derleme zamanı elde edersiniz.

Ama işte şu: bu, metin dahil etmeyi bir sınıfı birden çok yere teslim etmenin bir aracı olarak kullanma eseri.

Modüler bir dünyada, Java, C #, Python ve benzerleri gibi diğer dillerde gördüğümüz gibi, her üye işlevini sınıfın kendisinde tanımlamak isteyebilirsiniz. Bu, kodun yerini makul tutar ve aynı işlev imzasını yeniden yazmak zorunda kalmaz, böylece DRY'nin ihtiyaçlarını karşılar.

Ancak tüm üyeler sınıf tanımında tanımlanmışsa, o zaman eski kurallar altında bu üyelerin hepsi olacaktır inline. Ve bir modülün bir fonksiyonun olmasına izin vermesi için inline, ikili modül yapısının bu fonksiyonların tanımını içermesi gerekir. Bu, böyle bir işlev tanımında bir kod satırını bile her değiştirdiğinizde, modülün ona bağlı olarak her modülle birlikte yinelemeli olarak oluşturulması gerekecektir.

Örtülü inlinemodülleri kaldırmak , tanımlamayı sınıfın dışına taşımak zorunda kalmadan kullanıcılara metin içerme günlerinde sahip oldukları güçleri verir. Hangi işlev tanımlarının modülün bir parçası olduğunu, hangilerinin olmadığını seçebilirsiniz.


8

Bu , birkaç gün önce Prag'da kabul edilen P1779'dan geliyor . Tekliften:

Bu makale, (adlandırılmış) bir modüle eklenmiş bir sınıf tanımında tanımlanan işlevlerden örtülü satır içi durumun kaldırılmasını önermektedir. Bu, sınıfların gereksiz bildirimlerden kaçınarak, modül yazarlarına satır içi veya satırsız işlev bildirme esnekliğini koruyabilmelerini sağlar. Ayrıca, sınıf şablonlarının (sınıf tanımı dışında genel olarak tanımlanamayan) enjekte edilmiş arkadaşlarının hiç satır içi olmamasına izin verir. Ayrıca NB yorumu US90'ı da çözmektedir .

Makale (diğer şeylerin yanı sıra) cümleyi kaldırdı:

Sınıf tanımında tanımlanan bir işlev satır içi işlevdir.

ve cümleyi ekledi:

Genel modülde, sınıf tanımında tanımlanan bir işlev dolaylı olarak satır içi ([class.mfct], [class.friend]).


İle örnek export module Milk programın modüler eşdeğeri olacaktır. Derleyicilerin zaten açıklanmamış satır içi işlevler yaptığını, inlineyalnızca inlineanahtar kelimelerin sezgisel olarak varlığını kullandıklarını unutmayın .


Yani, inlineanahtar kelime içermeyen bir modüldeki fonksiyon derleyici tarafından asla satır içine alınmaz, değil mi?
metalfox

1
@metalfox Hayır, bunun doğru olduğuna inanmıyorum.
Barry

1
Anlıyorum. Teşekkürler. Bu, bir cpp dosyasında tanımlandığı gibi, bu da bağlantı zamanında satır çizilmeyeceği anlamına gelmez.
metalfox
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.