Şablon kesinti kılavuzları nelerdir ve bunları ne zaman kullanmalıyız?


89

C ++ 17 standardı "şablon kesinti kılavuzlarını" sunar. Standardın bu sürümünde tanıtılan kurucular için yeni şablon argüman çıkarımı ile ilgili olduklarını anlıyorum, ancak henüz ne oldukları ve ne için oldukları konusunda basit, SSS tarzı bir açıklama görmedim.

  • C ++ 17'de şablon kesinti kılavuzları nelerdir?

  • Neden (ve ne zaman) onlara ihtiyacımız var?

  • Onları nasıl beyan ederim?



Özellikle, herhangi bir kesinti kılavuzunun C ++ 17 STL tarafından sağlanıp sağlanmadığını bilmek isterim (örn. Std :: pair veya std :: tuple için). C ++ 17'den itibaren "çıkarılabilir" standart şablon türlerinin tam listesi nedir?
Quuxplusone


Herhangi bir derleyicinin bunu destekleyip desteklemediğini bilmek isterim. Gcc, clang ve vc ++ 'yı denedim. rextester.com/DHPHC32332 Nevermind, sadece gc ++ 8.1 C ++ 17 ve 2a g ++ -std = c ++ 17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Jean-Simon ile

Yanıtlar:


102

Şablon kesinti kılavuzları, derleyiciye bir dizi yapıcı argümanını (ve türlerini) sınıf için şablon parametrelerine nasıl çevireceğini söyleyen bir şablon sınıfıyla ilişkili kalıplardır.

En basit örnek, std::vectorbir yineleyici çifti alan kurucusudur.

template<typename Iterator>
void func(Iterator first, Iterator last)
{
  vector v(first, last);
}

Derleyici anlamaya ihtiyacı vector<T>'in Ttip olacaktır. Cevabın ne olduğunu biliyoruz; Tolmalıdır typename std::iterator_traits<Iterator>::value_type. Ama derleyiciye yazmak zorunda kalmadan nasıl söyleriz vector<typename std::iterator_traits<Iterator>::value_type>?

Bir kesinti kılavuzu kullanıyorsunuz:

template<typename Iterator> vector(Iterator b, Iterator e) -> 
    vector<typename std::iterator_traits<Iterator>::value_type>;

Bu, derleyiciye, vectorbu modelle eşleşen bir kurucu çağırdığınızda vector, sağdaki kodu kullanarak uzmanlığı çıkaracağını söyler .-> .

Türün argümanlardan çıkarılması, bu argümanlardan birinin türüne dayalı olmadığında kılavuzlara ihtiyacınız vardır. Bir ' vectorden a'yı başlatmak , initializer_listaçıkça vector' s 'yi kullanırT , bu nedenle bir rehbere ihtiyaç duymaz.

Sol tarafın mutlaka gerçek bir kurucu belirtmesi gerekmez. Çalışma şekli, bir tür üzerinde şablon yapıcı kesinti kullanırsanız, tüm kesinti kılavuzlarına göre ilettiğiniz argümanlarla eşleşmesidir (birincil şablonun gerçek oluşturucuları örtük kılavuzlar sağlar). Bir eşleşme varsa, türe hangi şablon bağımsız değişkenlerinin sağlanacağını belirlemek için bunu kullanır.

Ancak bu kesinti yapıldıktan sonra, derleyici tür için şablon parametrelerini anladığında, bu türdeki nesnenin başlatılması sanki hiçbiri olmamış gibi devam eder. Yani seçilen kesinti kılavuzunun kurucu ile eşleşmesi gerekmez .

Bu ayrıca, toplamalar ve toplu başlatma içeren kılavuzları kullanabileceğiniz anlamına gelir:

template<typename T>
struct Thingy
{
  T t;
};

Thingy(const char *) -> Thingy<std::string>;

Thingy thing{"A String"}; //thing.t is a `std::string`.

Bu nedenle kesinti kılavuzları yalnızca başlatılan türü bulmak için kullanılır. Gerçek başlatma süreci, belirleme yapıldıktan sonra tam olarak daha önce olduğu gibi çalışır.


7
Hmm, aklıma rehberle bile vector v{first, last};doğru şeyi yapmayacağını anladım :(
TC

3
@TC… doğru olan bir yineleyiciler vektörü oluşturmak değilse. Ve std::string{32,'*'}[0] == ' '(ASCII için). Ancak bunların hepsi C ++ 11'den beri doğrudur.
Arne Vogel

2
ayırıcı vektör parametresine ne olur? ayırıcı vektör parametresinde varsayılan bir bağımsız değişken olmazsa ne olur? (InputIterator'dan çıkaramazsınız)
gnzlbg

@NicolBolas: Örtük ve açık kesinti kılavuzlarının kısmen veya tamamen özelleştirilmiş sınıflar bağlamında nasıl çalışabileceğinin ayrıntılarını açıklar mısınız (kurucularının birincil şablonla eşleşen parametre türlerine sahip olması gerekmez)? Hızlı bir arama yoluyla bu konuda bilgi bulmak zor.
user541686

1
@NicolBolas: Anlıyorum. Sorunun açıkça tümdengelim kılavuzlarıyla ilgili olduğu bana açık değil ... Bu yoruma kelimenin tam anlamıyla yazdıklarınızı eklemenizin faydalı olacağını düşünüyorum.
user541686
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.