Geçerli durumda, C++ 11 (diyelim ki gcc 4.7.2), değişken argümanları alabilecek bir kurucuya ihtiyacım olduğunda variadic-template veya std::initializer_list
arasında nasıl seçim yapmalıyım?Kurucular için, variadic-templates vs std :: initializer_list arasında nasıl seçim yapabilirim?
cevap
Variadic bir şablon, farklı türlerde bağımsız değişkenler sağlarken, std::initializer_list
argümanın türü ile templated edilir. Bu, listedeki tüm öğelerin türünün aynı olması gerektiği (veya temeldeki türe dönüştürülebilmesi, ancak daraltma dönüşümlerine izin verilmemesi) anlamına gelir. Bunun sizin için tercih edilip edilmeyeceğine bağlı olarak, birini veya diğerini seçebilirsiniz.
Ayrıca variadic şablon benzer tip kesinti initializer_list
için gerçekleştirilemez yaparken, sözdizimsel formu T&&
lvalue referanslar ve rvalue referanslar hem bağlanabildiği içinde, mükemmel yönlendirme gerekiyorsa genellikle varsayılan seçimdir:
struct A
{
// Deduces T& for lvalue references, T for rvalue references, and binds to both
template<typename... Ts>
A(Ts&&...) { }
// This is an rvalue reference to an initializer_list. The above type deduction
// does not apply here
template<typename T>
A(initializer_list<T>&&) { }
};
Ayrıca tek tip başlatma sözdizimi (yani küme parantezleri) kullandığınızda bir initializer_list
kabul eden bir yapıcı uygulanabilir, yeni bir kurucu var olsa bile, varsayılan olarak çağrılan olacağını fark.
struct A
{
A(int i) { }
};
struct B
{
B(int) { }
B(std::initializer_list<A>) { }
};
int main()
{
B b {1}; // Will invoke the constructor accepting initializer_list
}
Mükemmel iletme hakkında biraz genişletme, 'std :: initializer_list
@LucDanton: İyi nokta. –
Ben variadic şablonları seçilmesi hep tavsiye ve mümkün std::initializer_list
kaçının: Bu ya sahip olmak istediklerine şey olabilir veya olmayabilir.
Bu
Birliktestd::vector
hayata nasıl olurdu C++ 11:
nedeni olarak oldu parantez türüne göre farklı davranışlara yol açabilir jenerik kodunda
initializer_list
kullanarak,
main
gösterdi edilir
#include <iostream>
#include <vector>
struct exp_sequence {
template <typename... T>
exp_sequence(T&&...) {}
};
struct from_arglist_t {} from_arglist;
template <typename T>
class my_vector {
std::vector<T> data;
public:
my_vector(int n, T const& e) : data(n, e) {}
template <typename... Args>
my_vector(from_arglist_t, Args&&... args) {
data.reserve(sizeof...(Args));
exp_sequence{(data.push_back(std::forward<Args>(args)),1)...};
}
std::size_t size() { return data.size(); }
};
int main()
{
std::vector<int> v1{13, 13}; std::cout << v1.size() << '\n'; // 2
std::vector<int> v2(13, 13); std::cout << v2.size() << '\n'; // 13
my_vector<int> v3{13, 13}; std::cout << v3.size() << '\n'; // 13
my_vector<int> v4(13, 13); std::cout << v4.size() << '\n'; // 13
my_vector<int> v5(from_arglist, 13, 13); std::cout << v5.size() << '\n'; // 2
my_vector<int> v6{from_arglist, 13, 13}; std::cout << v6.size() << '\n'; // 2
}
seçilen. Böyle bir kurucu ekleyerek kodu sessizce değiştirme olasılığı da vardır. variadic şablonla
//std::vector<move_only> m1{move_only{}}; // won't compile
my_vector<move_only> m2{from_arglist, move_only{}}; // works fine
'exp_sequence' hilesi düzgün, ancak öğeleri doğru sıraya yerleştirmeyi garanti ediyor mu? AFAIR, C ve C++, işlev argümanlarını sözcüksel olarak değerlendirmeyi taahhüt etmemişlerdir. Bu nedenle, varyantik şablon yapımcıları için argüman değerlendirme sırası hakkında C++ 11 standardında özel bir garanti yoksa, bu taşınabilir değildir. – fgp
@fgp: Argüman değerlendirme sırasının soldan sağa doğru sıralanması garanti edilir.Bu, brace initialisation'ın her kullanımında geçerlidir (bu nedenle exp_sequence'ın bir sınıf olması gerekir). @ipc – ipc
'{... (1 öne
, argüman sayısı (sizeof...
yoluyla ve erişilebilir) derleme sırasında bilinmektedir:
başka neden
hareket okunur türleridir.std::initializer_list
ile argüman sayısı sadece çalışma zamanında bilinir. Bu yüzden kararın bir kısmı, kaç argümanınızın bulunduğunu bilmek veya bilmek istediğiniz zamana bağlıdır.
kapsayıcı, tam durumda başlatılması gerektiğinden (push_back, vb.) Derleme zamanı boyutuna sahiptir. Eğer 'const (boyut) 'metodunun' constexpr' olarak işaretlenmediğini kastediyorsanız, bu C++ 11'de bir kusurdu ve C++ 14'te düzeltildi. Böylece, adlandırılmış bir 'initializer_list ', vb. boyutlarında şablonlar, birçok şekilde derleme zamanında kullanılabilir. ama elbette, belki de variadic seçenek olarak pek fazla yol değil! Bu _parameter_ –
Bir yapıcı olduğunu bir 'kurucu her yerinde farklı büyüklükteki başlatıcıları ile birden sitelerden çağrılabilir çünkü initializer_list', derleme sırasında bilinen bir büyüklüğe sahip değildir. – KnowItAllWannabe
Evet, harika bir nokta, daha önce tam düşünmüyordum :) –
- 1. Bellek bozulması :: initializer_list
- 2. copy vs std :: ints için hareket et
- 3. std :: string :: uzunluğu() std vs :: dize :: boyut()
- 4. Neden "std :: initializer_list" bir literal tür olarak tanımlanmadı?
- 5. Ansible sürümleri arasında nasıl geçiş yapabilirim?
- 6. Gezinme Denetleyicileri arasında nasıl geçiş yapabilirim?
- 7. Yuvalanmış initializer_list bellek sızıntılarına neden neden
- 8. clojureql iki tarih arasında seçim yapın
- 9. C++ 11 RNG'nin başlangıç durumu için yerel ve genel ayarlar arasında nasıl geçiş yapabilirim?
- 10. Vektörlerin haritası üzerinde bir initializer_list kullanma
- 11. Konsolda komut dosyası yürütürken nasıl rasgele seçim yapabilirim?
- 12. std :: ref bu işlev için yararlı nedir?
- 13. st ++ :: vector ve std :: array için C++ initializer_list davranışı neden farklı?
- 14. Seçim sütununda manuel olarak nasıl katma değer yapabilirim?
- 15. glMatrix, Sylvester ve CanvasMatrix arasında seçim yapma?
- 16. initializer_list ile isteğe bağlı yapıcı
- 17. Tablo güncelleniyor, 3 rastgele dizi arasında seçim yapma - nasıl?
- 18. jQuery için nasıl geçiş yapabilirim?
- 19. Bir ham dizideki memcpy eşdeğerini std :: vektörüne nasıl yapabilirim?
- 20. Java'da aynı adla iki yöntem arasında nasıl seçim yapılır
- 21. Std :: array nesnesi, başlatıcı listesiyle nasıl oluşturulur?
- 22. Cassandra, Membase, Hadoop, MongoDB, RDBMS vb. Arasında nasıl seçim yapılır?
- 23. Scala: curried kurucular
- 24. Java kurucular desen
- 25. GPS ve Ağ sağlayıcı arasında nasıl geçiş yapabilirim?
- 26. Çoklu kurucular scala
- 27. "Seçim" kapsamı nasıl ayarlanır ve VS 2015'te değiştirilsin
- 28. JQUERY. 'None' ve 'block' arasında nasıl geçiş yapabilirim?
- 29. Raylar 3.2.13 ve raylar 4.0.0 arasında nasıl geçiş yapabilirim?
- 30. Emacs-ess'de R oturumları arasında nasıl geçiş yapabilirim?
Emin değilim (bu bir yorumdur neden), ancak başlatıcı listesinin tümü aynı türde olmak zorundayken, variadic şablonlar farklı türleri işlemez mi? –
@JoachimPileborg, Kesinlikle doğru, daha sonra int ... 've' std :: initializer_list 'arasında seçim yapabilirsiniz. Kullanmak için daha doğal olanı seçelim diyorum. –
chris