C ++ şablonları sadece bir çeşit yüceltilmiş makro mu?


27

C ++ şablonları ve bunun gibi C # / Java jenerikleri arasındaki farklı karşılaştırmalardan

/programming/31693/what-are-the-differences-between-generics-in-c-and-java-and-templates-in-c/31929#31929

C ++ şablonlarının bir çeşit ön işleme (derlemeden önce düz metin değiştirme) tarafından derlendiğine dair bir algıya sahip oldum. Çünkü C ++ şablonlarındaki kontrol tipi C makrolarına benzemektedir. Yani, bazı hatalar varsa, şablonların kendisinden değil, şablonlanmış kod bloklarını işledikten sonra oluşturulan kodun hatalarıdır. Başka bir deyişle, bunlar yalnızca C'deki makroların bir tür üst sürümleridir.

Sonra bunu destekleyen başka gerçekler buldum.

  • C ++ şablonlar önişlemeyle uygulanırsa, dinamik bağlantıda (.dll kullanarak) sorun olacağını düşünmüştüm. Ve hızlı bir googling bunu destekledi.

  • Başka bir nokta, tamsayı sabitleri şablonlara argüman olarak geçirilebilir. Hatta bir nevi özyinelemeyi bile destekliyor. Ancak bu özyineleme derlenmiş montaj / makine kodunda bulunamadı. Özyineleme işi derleme zamanlarında her özyinelemeli çağrı için bir fonksiyon üreterek ve böylece daha büyük fakat daha hızlı bir çalıştırılabilir ikili dosyaya sahip olarak yönetilir.

C makrolarının aksine, bazı üstün yetenekleri vardır. Ancak C ++ şablonu bir çeşit ön işleme ile uygulanmadı mı? Bu, farklı C ++ derleyicilerinde nasıl uygulanır?


19
Hayır! C ++ şablonları derlenir.
Edward Strange

2
"Ön işleme" tanımınız nedir? Ve "derleme" den? Yeterince geniş bir "önişleme" tanımı, bir derleyicinin yaptığı her şeyi içerebilir; Sonuçta, bir derleyici kaynak çalıştırılmadan önce gerçekten gerçekten işlemektedir, değil mi?
James McNellis

@James McNellis IMHO, önişlemeyi derleme için yapılan diğer tüm işlemlerden farklılaştırabilirseniz, sorumu anlamak yeterlidir. Önişlemci- en.wikipedia.org/wiki/Preprocessor#Lexical_preprocessors'ın
Gulshan

6
Bu ön işleme biçiminden bahsediyorsanız, hayır, C ++ şablonları kesinlikle yalnızca bir çeşit yüceltilmiş makro değildir.
James McNellis

1
Şablon dili aslında tamamlanmış durumdadır, bu yüzden gelişmiş makrolardan çok daha fazlasıdır.
davidk01

Yanıtlar:


9

C ++ şablonları Lisp (ya da daha fazlası, Scheme) makrolarının bir tür aşağılanmış makrolarıdır. Derleme zamanını değerlendiren bir Turing-tamamlanmış bir dildir, ancak bu dilden altta yatan C ++ ortamına erişim olmadığı için oldukça kısıtlıdır. Bu nedenle, evet, C ++ şablonları bir tür ön işleme biçimi olarak görülebilir, bu da üretilen kodla çok sınırlı bir etkileşimde bulunur.


2
"ancak bu dilden altta yatan C ++ ortamına erişim olmadığı için oldukça sınırlı." -- Bunun anlamı ne? Bu ifadeyi ayrıştırmaya çalıştım ama başarısız oldum.
quant_dev

2
Aslında, aslında ... github.com/kmichel/bf0x
Anton Golov

3
SK-mantık @: Bir kenara, C ++ 11 gibi olduğu C ++, siz (ukalalıkla) farklı dilde aynı dilde farklı sürümlerini tedavi sürece.
Jon Purdy,

3
@Jon Purdy, C ++ 11 bu resmi cevap sırasında yoktu (resmen). Günümüzde bir örnek, bir veri yapısının ayrıştırılması, bir kütüphane işlevi vb. Kullanılarak daha karmaşık bir hal alacaktır.
SK-mantık

1
@ SK-mantık: C ++ 'ın Lisp benzeri makrolarla uygulandığını biliyor musunuz? Şablon kısıtlamalarından bıktım. Haxe'de güçlü makro sistemine sahip C ++ tarzı bir sözdizimi dili örneği: haxe.org/manual/macros . (Bana yardım etmiyor çünkü C ++ 'ı amacına uygun kullanıyorum - 8-bit mikrodenetleyicileri programlamak; başka bir şey için daha iyi diller var).
pfalcon

41

Muhtemelen en büyük fark, başka bir derleme yapılmadan önce ön işleme aşamasında C makrolarının genişlemesi ve C ++ şablonlarının derlemenin bir parçası olmasıdır. Bu, C ++ şablonlarının başka şeylerin yanı sıra, tip farkında ve kapsamlı olduğu ve basit metinsel değiştirme olmadığı anlamına gelir. Gerçek işlevleri derleyebilir ve bu nedenle makroların sahip olduğu sorunların çoğundan kaçınırlar. Yazının farkına varmak, genel veya uzman olabileceği anlamına gelir: örneğin, bir swapşablon işlevi sağlamak kolaydır ve nesneler yığın belleği yönetse bile iyi çalışan uzmanlıklar yazmak kolaydır.

Bu nedenle: C ++ şablonları aynı şekilde önişlemiyorlar, makrolar bir tür C makrosu değiller ve hangi şablonların yaptığını kopyalamak için C makrolarını kullanmak imkansız.

Şablonlar başlık dosyalarında, bağlantılı kitaplıklarda değil, doğru olarak yaşar, ancak bir .dll sağlıyorsanız, muhtemelen kullanması için bir başlık dosyası da sağlarsınız.


12
Başlık dosyasında yaşamaları gerekmez (bu, onları kullanmak için en basit tekniktir). Bunları bir kaynak dosyada tanımlayabilir ve kaynak dosyadaki (derleme birimi) şablonun el ile başlatılmasını zorlayabilirsiniz. Bağlama daha sonra başlatmaları normal olarak algılar (bu, şablonları belirli türlerle sınırlamak ve tüm genel türlere izin vermemek için bir tekniktir).
Martin York

@ Martin: Bu tekniğin (desteklenirken) aslında standart tarafından açıkça desteklendiğinden emin değilim. Aksi halde tüm derleyiciler exportçoktan uygulanmış olacaktı . İşlevler için işe yaradığını biliyorum, ama sınıflar için işe yaradığından şüpheliyim: boyutlarını nasıl bildin?
Matthieu M.

@Matthieu M: Bunun export anahtar kelimesiyle ilgisi yok. "Açık" şablon örneklemesini ele alır ve standartta iyi tanımlanır.
Martin York

2
@Matthieu M .: Derleyici bir fonksiyonun imzasını biliyorsa ve linker bir uygulama bulabilirse her şey yolunda demektir. Bu, işlevin bir şablon işlevi olup olmadığını uygular. Uygulamada, genellikle başlık dosyalarında yaşarlar, çünkü belirli örneklemeleri zorlamak tipik olarak değerinden fazla çalışır, ancak Martin alternatifi belirtmekte haklıdır.
David Thornley

Özel fonksiyonlar için kesinlikle işe yaradığını biliyorum. Ancak, aynı zamanda benim açımdan sınıflar için işe yaramadığından eminim. Bunun da uzmanlık sınıflarındaki yöntemlerde işe yaradığını düşünüyorum, ancak bunun standart olup olmadığını bilmiyoruz.
Matthieu M.

5

Nasıl uygulandıkları önemli mi? İlk C ++ derleyicileri, kodu ac derleyicisine besleyen yalnızca ön işlemcilerdi, C ++ yalnızca yüceltilmiş bir makro olduğu anlamına gelmez.

Şablonlar, birden fazla tür için kod uygulamanın daha güvenli, daha verimli ve özelleştirilebilir (bunun gerçek bir kelime olduğunu sanmıyorum) yolu sağlayarak makro gereksinimini ortadan kaldırır.

Basit yazım kodunu c cinsinden yapmanın çeşitli yolları vardır, basit türlerin ötesine geçtiğinizde hiçbiri çok iyi değildir.


C ++ 'nın yüceltilmiş bir makro olduğunu söylemedim. C ++ 'a çok hayranım. Sadece meraklı olmak.
Gulshan

2
@Gulshan: Hayır, bunun hakkında hiçbir şey söylemediniz. Bununla birlikte, C ++ derleyicileri bu kadar erken çalıştı (CFront'un yalnızca bir makroişlemci yerine derleyici bir şey olması dışında) ve C ++ şablonları hakkındaki ifadeleriniz C ++ 'ın başına uygulanabilir.
David Thornley

CFront , C ++ 'dan C +' ya derlenmiştir. Önişlemci ile derleyici arasındaki çizgi açıkça tanımlanmıştır: bir derleyici girişini anlamaya çalışır - ayrıştırma, AST binası ve & c.
Jon Purdy

1
David'in kastettiği, C ++ 'nın altında yatan bir altkümenin olduğu ve şablonların bu altkümede bir programı genel olarak kullanılan, daha sonra ayrı bir aşama olarak derlenebilecek bir tür makro olarak düşünülebileceğini düşünüyorum.
Giorgio,

5

Bazı farklılıklar var; örneğin, gerektiğinde bir fonksiyon aşırı yüklenmesini başlatmak için şablonlar kullanılabilirken, makrolarda, makroyu derleyici tarafından görülebilir kılmak için olası her aşırı yüklenme için bir kez genişletmeniz gerekir. kullanılmayan kod

Başka bir fark ise şablonların isim alanlarını onurlandırmasıdır.


2

IMHO, C ++ şablonları ve C Makroları tamamen farklı iki sorunu çözmeyi amaçlıyordu. Orijinal C ++ Standart Şablon Kütüphanesi, konteyner sınıflarını (diziler, bağlantılı listeler, vb.) Genel olarak uygulanan genel işlevlerden (sıralama ve birleştirme gibi) temiz bir şekilde ayırma mekanizmasıydı. Verimli algoritmalar ve veri yapılarının soyut temsillerine sahip olmak, daha etkileyici bir koda yol açar, çünkü belirli bir veri parçası üzerinde çalışan bir işlevin en iyi nasıl uygulanacağı konusunda önemli ölçüde daha az tahmin çalışması vardır. C makroları, Lisp makrolarında tipik olarak görecekleri ile daha uyumluydu, bu nedenle dili satır içi kodla "genişletmek" için bir araç sağladılar. İşin güzel yanı, C ++ Standart Kütüphanesi, #define için C de kullandığımız şeylerin çoğunu kapsayacak şekilde şablonların işlevselliğini genişletti.

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.