2016'nın aydınlanmış çağında, bu soru sorulduğundan beri iki yeni standart ve hemen köşemizde yeni bir standart ile, bilinmesi gereken en önemli şey , C ++ 17 standardını destekleyen derleyicilerin kodunuzu olduğu gibi derleyeceğidir. .
C ++ 17'deki sınıf şablonları için şablon bağımsız değişkeni çıkarımı
Burada (kabul edilen cevaba Olzhas Zhumabek tarafından yapılan bir düzenlemenin izniyle), standarttaki ilgili değişiklikleri detaylandıran kağıt bulunmaktadır.
Diğer cevaplardan gelen endişeleri ele almak
Mevcut en yüksek puanlı cevap
Bu yanıt, "kurucuyu kopyala operator=
" nın doğru şablon uzmanlıklarını bilmediğine işaret eder.
Standart kopyalama yapıcı çünkü bu, saçmalık operator=
var sadece bir için bilinen şablon tipi:
template <typename T>
class MyClass {
MyClass(const MyClass&) =default;
... etc...
};
// usage example modified from the answer
MyClass m(string("blah blah blah"));
MyClass *pm; // WHAT IS THIS?
*pm = m;
Ben açıklamalarda belirtildiği gibi burada, orada hiçbir neden için MyClass *pm
birlikte veya çıkarımın yeni formu olmadan yasal bir deklarasyon olmak: MyClass
bir tür değil o bir işaretçi ilan etme mantıklı değil bu yüzden, (öyle bir şablon var) yazın MyClass
. İşte örneği düzeltmenin olası bir yolu:
MyClass m(string("blah blah blah"));
decltype(m) *pm; // uses type inference!
*pm = m;
Burada pm
ise zaten çıkarım önemsiz doğru tipte ve böylece. Dahası, kopya yapıcıyı çağırırken türleri yanlışlıkla karıştırmak imkansızdır :
MyClass m(string("blah blah blah"));
auto pm = &(MyClass(m));
Burada pm
bir kopyasına işaretçi olacak m
. Burada, MyClass
gelen kopya inşa ediliyor m
-ki tiptedir MyClass<string>
(ve değil varolmayan Çeşidi MyClass
). Bu nedenle, bir noktada pm
çeşidini çıkarılır, var olan bir kalıp-türü bir bilmek yeterli bilgi m
, ve bu yüzden de kalıp-türü pm
vardır string
.
Ayrıca, aşağıdakiler her zaman bir derleme hatası doğurur :
MyClass s(string("blah blah blah"));
MyClass i(3);
i = s;
Bunun nedeni, kopya oluşturucunun bildiriminin şablonlu olmamasıdır :
MyClass(const MyClass&);
Burada, kopya-yapıcı bağımsız değişkeninin şablon türü, genel olarak sınıfın şablon türü ile eşleşir ; yani, ne zaman MyClass<string>
somutlaştırılır, MyClass<string>::MyClass(const MyClass<string>&);
onunla somutlaştırılır ve ne zaman MyClass<int>
somutlaştırılırsa MyClass<int>::MyClass(const MyClass<int>&);
somutlaştırılır. Açıkça belirtilmedikçe veya şablonlaştırılmış bir kurucu bildirilmedikçe, derleyicinin somutlaştırması için bir neden yoktur MyClass<int>::MyClass(const MyClass<string>&);
, bu açıkça uygunsuz olacaktır.
Cevap Cătălin Pitiș
Pitiș, çıkarım yapan bir örnek verir Variable<int>
ve Variable<double>
ardından şunu belirtir:
Kodda iki farklı tür için (Değişken ve Değişken) aynı tür adıma (Değişken) sahibim. Öznel bakış açıma göre, kodun okunabilirliğini oldukça fazla etkiliyor.
Önceki örnekte belirtildiği gibi , yeni özellik sözdizimsel olarak öyle görünmesine rağmen , Variable
kendisi bir tür adı değildir .
Pitiș daha sonra uygun çıkarıma izin verecek bir kurucu verilmemesi durumunda ne olacağını sorar. Cevap, çıkarıma izin verilmediğidir, çünkü çıkarım yapıcı çağrısı tarafından tetiklenir . Bir kurucu çağrısı olmadan, hiçbir çıkarım yoktur .
Bu, foo
burada hangi sürümün çıkarıldığını sormaya benzer :
template <typename T> foo();
foo();
Cevap, belirtilen nedenle bu kodun yasa dışı olmasıdır.
MSalter'ın cevabı
Anladığım kadarıyla, önerilen özellik hakkında meşru bir endişeyi ortaya çıkarmanın tek cevabı bu.
Örnek şudur:
Variable var(num); // If equivalent to Variable<int> var(num),
Variable var2(var); // Variable<int> or Variable<Variable<int>> ?
Buradaki anahtar soru, derleyici burada türden türetilen yapıcıyı mı yoksa kopya oluşturucuyu mu seçiyor ?
Kodu denediğimizde, kopya yapıcısının seçildiğini görebiliriz. Örneği genişletmek için :
Variable var(num); // infering ctor
Variable var2(var); // copy ctor
Variable var3(move(var)); // move ctor
// Variable var4(Variable(num)); // compiler error
Teklifin ve standardın yeni versiyonunun bunu nasıl belirttiğinden emin değilim; henüz anlamadığım yeni bir standart olan "kesinti kılavuzları" tarafından belirleniyor gibi görünüyor.
Ayrıca var4
kesintinin neden yasa dışı olduğundan da emin değilim ; g ++ 'dan derleyici hatası, ifadenin bir işlev bildirimi olarak ayrıştırıldığını gösteriyor gibi görünüyor.